Launch new Mento Stablecoins [JPY, GBP, AUD, CAD, CHF, NGN, ZAR]

Hey folks, the first proposal to enable the oracles needed for the launch of cCHF, cNGN, and cJPY stable coins is currently in the voting phase: CGP180

A second proposal will be submitted for voting to officially launch the following stable tokens:

  • cCHF (Swiss Franc)
  • cNGN (Nigerian Naira)
  • cJPY (Japanese Yen)

This post serves as a guide to help verify the transactions that will activate these new stable tokens and integrate them into the Mento protocol.

We have prepared for this launch by:

  • Testing the proposals on Alfajores
  • Simulating the proposals on a fork of Celo Mainnet
  • Running comprehensive tests against the fork

The transactions for the CGP will be broken down into the following sections, with transaction indices in brackets:

  1. Initialization of Stable Tokens (0-20)
  2. Configure Exchanges & Trading Limits (21-32)
  3. Configure BreakerBox (33-35)
  4. Configure MedianDeltaBreaker (36-38)

Before diving into each section and transaction, it would be useful to have the following available so you can follow along:

For the tech-savvy, you can find everything we are describing here in our deployment tooling repository as code, in the file FX03.sol. To verify that the addresses included in the proposal are correct, please refer to the Appendix at the bottom for guidance.

1. Initialization of the Stable Tokens

For each stable token (cCHF, cNGN, cJPY), the initialization process includes:

  • Initializing the proxy token contract & setting its implementation address
  • Calling the StableTokenV2 initializer
  • Configuring constitution parameters for various token functions
  • Adding the token to the Reserve
  • Whitelisting as a gas currency

Specific verification steps are included for each transaction, such as:

  • Verifying proxy and implementation contract addresses
  • Checking initialization parameters
  • Confirming governance and function thresholds

The table below details the initialization transactions for the new stable tokens, including their symbols, full names, contract names, and the corresponding transaction number ranges.

Symbol Name Contract Name Initialization Txs
cCHF Celo Swiss Franc StableTokenCHFProxy 0 - 6
cNGN Celo Nigerian Naira StableTokenNGNProxy 7 - 13
cJPY Celo Japanese Yen StableTokenJPYProxy 14 - 20

Below is a breakdown of the initialization transactions for cCHF, the same verification steps apply to all other stable tokens.

TX#0 - initialize the stable token proxy contract and set its implementation address

The proxy contract has been deployed and verified on Celo mainnet. Immediately after, ownership of the proxy contract was transferred to governance. This transaction has two arguments, the first being the address of the StableTokenV2 implementation and the second being the initialisation parameters.

  • Verify the StableTokenCHFProxy address: 0xb55a79f398e759e43c95b979163f30ec87ee131d
  • Verify the StableTokenV2 implementation address
  • Verify the initialization parameters for the new stable token:
    • name: Celo Swiss Franc
    • symbol: cCHF
    • initialBalanceAddresses: [] (no pre-mint)
    • initialBalanceValues: [] (no pre-mint)

TX#1 - Call StableTokenV2 initializer

  • Verify the StableTokenCHFProxy address
  • Verify the StableTokenV2 implementation address
  • Verify the initialization parameters:
    • broker: - Verify the broker proxy address
    • validators: - Verify the validators address
    • exchange: address(0) - Exchanges have been deprecated and replaced by the broker

TX#2 - set constitution parameters for transfer(address,uint256)

  • Verify the GovernanceProxy address
  • Verify the StableTokenCHFProxy address
  • Verify the function selector: bytes4(keccak256(bytes("transfer(address,uint256)")))
  • Verify the threshold: 0.9 * 1e24 (same as existing stables)

TX#3 - set constitution parameters for transferWithComment(address,uint256,string)

  • Verify the GovernanceProxy address
  • Verify the StableTokenCHFProxy address
  • Verify the function selector: bytes4(keccak256(bytes("transferWithComment(address,uint256,string)")))
  • Verify the threshold: 0.6 * 1e24 (same as existing stables)

TX#4 - set constitution parameters for approve(address,uint256)

  • Verify the GovernanceProxy address
  • Verify the StableTokenCHFProxy address
  • Verify the function selector: bytes4(keccak256(bytes("approve(address,uint256)")))
  • Verify the threshold: 0.6 * 1e24 (same as existing stables)

TX#5 - add cCHF as a stable token to the Reserve

  • Verify the ReserveProxy address
  • Verify the StableTokenCHFProxy address

TX#6 - whitelist cCHF as a gas currency

  • Verify the FeeCurrencyWhitelistProxy address
  • Verify the StableTokenCHFProxy address

2. Configure the new exchanges and trading limits

:warning: Verification tip: As in previous proposals, we recommend ignoring the args field from celocli and focusing on params, as well as ignoring the numbered fields and instead focusing only on the named fields. This is due to how nested structs are serialized by celocli, which may make the payload look confusing.

The table below details the transactions for the exchange creation and trading limit configuration

Exchange Txs
cCUSD < - > cCHF 21 - 23
cCUSD < - > cNGN 24 - 26
cCUSD < - > cJPY 27 - 29

Below is a breakdown of the trading limit configuration and exchange creation for the cCUSD/cCHF exchange, the same verification steps apply to all other exchanges.

Create & configure exchange

The pool configuration structures are documented here: https://docs.mento.org/mento/developers/smart-contracts/bipoolmanager

TX#21 - Create the cUSD/cCHF exchange

  • Verify the BiPoolManagerProxy address
  • Verify the exchange configuration

Configure trading limits

The TradingLimit.Config structure is documented here: Mento Trading Limits

TX#22 - Configure trading limits on cUSD for the cUSD/cCHF exchange

  • Verify BrokerProxy address
  • Verify the arguments:
    • exchangeId: the deterministic id of the cUSD/cCHF exchange
    • token: which asset in the pair to target, in this case, the cUSD token address
    • config: the trading limit configuration

TX#23 - Configure trading limits on cCHF for the cUSD/cCHF exchange

  • Verify Broker address
  • Verify the arguments:
    • exchangeId: the deterministic id of the cUSD/cCHF exchange
    • token: which asset in the pair to target, in this case, the cCHF token address
    • config: the trading limit configuration

3. Configure CircuitBreaker

Each new exchange requires a rate feed that must be monitored for stability. The circuit breaker system performs this monitoring through two configuration steps:

  1. Configure the breaker box to track rate changes
  2. Set up monitoring thresholds through the median delta breaker

The table below details the ratefeed name, its ID and the corresponding transactions for the BreakerBox configuration.

Rate Feed Rate Feed Id Txs
relayed:CHFUSD 0x0f61BA9c30ef7CaEE7E5CC1F96BFFCb0f52ccD64 30 - 34
relayed:NGNUSD 0xC13D42556f1baeab4a8600C735afcd5344048d3C 35 - 39
relayed:JPYUSD 0xFDE35B45cBd2504FB5dC514F007bC2DE27034274 40 - 44

Below is a breakdown of the circuit breaker configuration for the CHF/USD rate feed. The same verification steps apply to all other rate feeds.

Configure the BreakerBox

Here we configure the BreakerBox to ensure it monitors changes to the new CHF/USD rate.

TX#30 - Add rate feed to the BreakerBox:

  • Verify the BreakerBox address
  • Verify the arguments:
    • newRateFeedIDs an array of oracle feed ids. In this case, the array only contains the id of CHF/USD
      • CHF/USD - address(uint160(uint256(keccak256("relayed:CHFUSD"))))

TX#31 - Enable the MedianDeltaBreaker for the CHF/USD rate feed

  • Verify the BreakerBox address
  • Verify the arguments:
    • breakerAddress should be the MedianDeltaBreaker
    • rateFeedID should be the identifier for the CHF/USD rate, i.e. address(uint160(uint256(keccak256("relayed:CHFUSD"))))
    • enable true

Configure the MedianDeltaBreaker

These transactions configure the MedianDeltaBreaker with the appropriate values needed to determine when the breaker should trip for the CHF/USD rate feed and how much time should pass before the breakers can be reset.

TX#32 - Set the cooldown time on the MedianDeltaBreaker for the CHF/USD rate feed

  • Verify the MedianDeltaBreaker address
  • Verify the arguments:
    • rateFeedIDs: the array of rate feeds to configure:
      • CHF/USD: address(uint160(uint256(keccak256("relayed:CHFUSD"))))
    • cooldownTimes: the array of cooldown times to be configured per rate feed. The values are in seconds.
      • CHF/USD: 15 minutes = 900s

TX#33 - Set the rate change thresholds on the MedianDeltaBreaker for the CHF/USD rate feed

  • Verify the MedianDeltaBreaker address
  • Verify the arguments:
    • rateFeedIDs: the array of rate feeds to configure:
      • CHF/USD: address(uint160(uint256(keccak256("relayed:CHFUSD"))))
    • rateChangeThresholds: The array of rate change thresholds to be configured per rate feed. The values are fixed-point numbers – a number with 24 decimals, i.e. 1 is written as 1e24.
      • CHF/USD: 4e22 = 4%

TX#34 - Set the smoothing factor on the MedianDeltaBreaker for the CHF/USD rate feed

  • Verify the MedianDeltaBreaker address
  • Verify the arguments:
    • rateFeedID: The id of the rate feed to be updated
      • CHF/USD: address(uint160(uint256(keccak256("relayed:CHFUSD"))))
    • newSmoothingFactor: The new smoothing factor value. The value is a fixed point number, similar to the rate change threshold.
      • CHF/USD: 5e21 = 0.5%

Appendix: Verifying an address

Verifying that an address in the CGP is correct requires a few different strategies depending on what that address is (see the mento docs for some additional information). Here are common situations:

  • Is it a rate feed identifier like: address(uint160(keccack256("relayed:CHFUSD")))
    • Use Keccak-256 Online 2 to compute the keccak
    • Take the last 40 characters (20 bytes) of the keccak and compare with the value
  • Is it a Mento contract?
  • Is it a Core Celo contract?
    • Yes:
      • It’s probably GoldToken or FeeCurrencyDirectory which can be both verified in the Celo Registry
3 Likes