Hi Folks, The first proposal to enable the oracles needed for the launch of cGBP, cAUD, cCAD, cCHF, and cZAR stable coins has been submitted:
https://mondo.celo.org/governance/cgp-177
A second proposal CGP-0178 has also been submitted for voting and will officially launch the following stable tokens:
- cGBP (British Pound)
- cZAR (South African Rand)
- cCAD (Canadian Dollar)
- cAUD (Australian Dollar)
https://mondo.celo.org/governance/cgp-178
Note: Follow-up proposals for the oracle whitelist and launch of cJPY, cNGN, and cCHF will be submitted in the coming weeks
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. You can follow along with the raw transactions found in the mainnet.json file in the Celo governance repo.
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:
- Initialization of Stable Tokens (0-27)
- Configure Exchanges & Trading Limits (28-39)
- Configure Circuit Breaker (40-59)
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 FX01.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 (cGBP, cZAR, cCAD, cAUD), 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 |
cGBP |
Celo British Pound |
StableTokenGBPProxy |
0 - 6 |
cZAR |
Celo South African Rand |
StableTokenZARProxy |
7 - 13 |
cCAD |
Celo Canadian Dollar |
StableTokenCADProxy |
14 - 20 |
cAUD |
Celo Australian Dollar |
StableTokenAUDProxy |
21 - 27 |
Below is a breakdown of the initialization transactions for cGBP, 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 StableTokenGBPProxy address
- Verify the StableTokenV2 implementation address
- Verify the initialization parameters for the new stable token:
- name:
Celo British Pound
- symbol:
cGBP
- initialBalanceAddresses:
[]
(no pre-mint)
- initialBalanceValues:
[]
(no pre-mint)
TX#1 - Call StableTokenV2 initializer
- Verify the StableTokenGBPProxy 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 StableTokenGBPProxy 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 StableTokenGBPProxy 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 StableTokenGBPProxy address
- Verify the function selector:
bytes4(keccak256(bytes("approve(address,uint256)")))
- Verify the threshold:
0.6 * 1e24
(same as existing stables)
TX#5 - add cGBP as a stable token to the Reserve
- Verify the ReserveProxy address
- Verify the StableTokenGBPProxy address
TX#6 - whitelist cGBP as a gas currency
- Verify the FeeCurrencyWhitelistProxy address
- Verify the StableTokenGBPProxy address
2. Configure the new exchanges and trading limits
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 < - > cGBP |
28 - 30 |
cCUSD < - > cZAR |
31 - 33 |
cCUSD < - > cCAD |
34 - 36 |
cCUSD < - > cAUD |
37 - 39 |
Below is a breakdown of the trading limit configuration and exchange creation for the cCUSD/cGBP 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#28 - Create the cUSD/cGBP exchange
- Verify the BiPoolManagerProxy address
- Verify the exchange configuration
Configure trading limits
The TradingLimit.Config structure is documented here: Mento Trading Limits
TX#29 - Configure trading limits on cUSD for the cUSD/cGBP exchange
- Verify BrokerProxy address
- Verify the arguments:
- exchangeId: the deterministic id of the cUSD/cGBP exchange
- token: which asset in the pair to target, in this case, the cUSD token address
- config: the trading limit configuration
TX#30 - Configure trading limits on cGBP for the cUSD/cGBP exchange
- Verify Broker address
- Verify the arguments:
- exchangeId: the deterministic id of the cUSD/cGBP exchange
- token: which asset in the pair to target, in this case, the cGBP 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:
- Configure the breaker box to track rate changes
- 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:GBPUSD |
0xf590b62f9cfcc6409075b1ecAc8176fe25744B88 |
40 - 44 |
relayed:ZARUSD |
0x17ef04Af0c52465694a841552fc2415169b1114c |
45 - 49 |
relayed:CADUSD |
0x20869cF54Ead821C45DFb2aB0C23d2e10Fbb65A4 |
50 - 54 |
relayed:AUDUSD |
0x646bD504C3864Ea5b8A6B6D25743721f61864A07 |
55 - 59 |
Below is a breakdown of the circuit breaker configuration for the GBP/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 GBP/USD rate.
TX#40 - 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 GBP/USD
- GBP/USD -
address(uint160(uint256(keccak256("relayed:GBPUSD"))))
TX#41 - Enable the MedianDeltaBreaker for the GBP/USD rate feed
- Verify the BreakerBox address
- Verify the arguments:
- breakerAddress should be the MedianDeltaBreaker
- rateFeedID should be the identifier for the GBP/USD rate, i.e.
address(uint160(uint256(keccak256("relayed:GBPUSD"))))
- enable true
Configure the MedianDeltaBreaker
These transactions configure the MedianDeltaBreaker with the appropriate values needed to determine when the breaker should trip for the GBP/USD rate feed and how much time should pass before the breakers can be reset.
TX#42 - Set the cooldown time on the MedianDeltaBreaker for the GBP/USD rate feed
- Verify the MedianDeltaBreaker address
- Verify the arguments:
- rateFeedIDs: the array of rate feeds to configure:
- GBP/USD:
address(uint160(uint256(keccak256("relayed:GBPUSD"))))
- cooldownTimes: the array of cooldown times to be configured per rate feed. The values are in seconds.
- GBP/USD: 15 minutes = 900s
TX#43 - Set the rate change thresholds on the MedianDeltaBreaker for the GBP/USD rate feed
- Verify the MedianDeltaBreaker address
- Verify the arguments:
- rateFeedIDs: the array of rate feeds to configure:
- GBP/USD:
address(uint160(uint256(keccak256("relayed:GBPUSD"))))
- 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.
TX#44 - Set the smoothing factor on the MedianDeltaBreaker for the GBP/USD rate feed
- Verify the MedianDeltaBreaker address
- Verify the arguments:
- rateFeedID: The id of the rate feed to be updated
- GBP/USD:
address(uint160(uint256(keccak256("relayedGBPUSD"))))
- newSmoothingFactor: The new smoothing factor value. The value is a fixed point number, similar to the rate change threshold.
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:GHSUSD”)))
- 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?
- Did it exist prior to MU01? (e.g. SortedOracles, StableToken, etc)
- Yes:
- It’s probably a proxy so you can check the addresses in the docs: Addresses - Mento Protocol 1
- You can also query the Registry contract on the target network
- No:
- Is it a Core Celo contract?
- Yes:
- It’s probably GoldToken or FeeCurrencyDirectory which can be both verified in the Celo Registry