Colony contract
Overview
A Colony involves the deployment and usage of two contracts one for each layers. For example, if the Colony is Optimism/Ethereum there will be two contracts:
Colony contract on L2 for the Optimism side
Colony contract on L1 for the Ethereum side
Taking an Optimism/Ethereum colony as reference, the scheme of the operation is as follows:
Colony L2 contract receives tokens(ERC20 and/or ETH) according to your business logic
Tokens are moved from Colony L2 contract to Optimism Bridge
Tokens are moved from Optimism Bridge to Colony L1 contract
Colony L1 contract sends tokens to your custom receiver address (wallet/smart contract)
Colony Smart Contract
The AbstractColony
contract is an abstract contract that can be inherited to code both the Colony contracts on the two Layers.
AbstractColony
is in fact a general purpose contract with several virtual
methods that can be overridden to create custom logic depending on the Layer of use.
AbstractColony
can handle ETH, Weth and ERC20s on both Layers.
The AbstractColony
contract is a LazyInitCapableElement
.
Methods
Contract Initialization
Your Colony contract inheriting the AbstractColony
can be initialized using the constructor
or the lazyInit
method provided by LazyInitCapableElement
.
It allows the following parameters to be initialized:
_wethAddresses
-> weth token address to use regarding the layer you're deploying.receiverResolver
-> address receiving the tokens from the Colony contract whensendTokens
is called (ifresolveReceiver()
is not overridden with custom logic).executorRewardPercentage
-> this is the percentage of the tokens that thesendTokens
function caller will receive as a reward.lazyInitResponse
-> additional encoded parameters to initialize (look below the following code box).
It also provides the virtual method _colonyLazyInit
that can be overridden to initialize additional parameters in the contract passed as bytes
lazyInitResponse
.
sendTokens
It is an external
method callable by anyone to send the tokens in the contract to the address that the resolveReceiver()
method returns.
It takes as input:
tokenAddresses
-> Addresses of tokens held by theColony
contract to be transferred. If an address equal to_wethAddresses
is passed it is first automatically unwrapped in ETH and then sent._l1GasArray
-> Gas limit required to complete the withdraw on L1. This parameter can be used if the Colony contract sends token to a Bridge which requires the_l1GasArray
parameter to bridge tokens (such as the Optimism standard Bridge)._rewardReceiver
-> Executor reward receiver.
It provides an executor reward for the msg.sender
of the call. For each token transferred by sendToken
(each address of tokenAddresses
array) the executor reward amount calculated as token amount to be transferred * executor reward percentage
is sent to the function caller as a reward.
customize the sendTokens logic
The sendTokens
method internally calls the internal virtual _send
method:
If not overridden, it simply sends the tokens held by the Colony contract to the address that the resolveReceiver()
method returns and the executor reward percentage to the address executor of the call.
However being a virtual method it can be overrode to build custom logic. For example in the case of Colony contract L2 the _send
call can call the Optimism bridge to move the tokens to L1. Or in case of Colony contract L1 the send call can call send tokens to a specific L1 contract such as an Organization Component smart contract.
resolveReceiver
If not overrode, the resolveReceiver()
method always returns the receiverResolver
address parameter.
However being a virtual method it can be overridden to get a dynamic receiver or a receiver different from receiverResolver
.
Colony Smart Contracts Use Case
EthereansOS Colonies contracts are used to move fees earned on Optimism to Ethereum.
The money flow of the operations is as follows:
Factory on L2 to Colony L2 (via FoF) when a guy does a transaction. ex: withdraw liquidity on Farming Factory
from Colony L2 to Bridge OP (with executor reward)
from OP Bridge to Colony L1. With one transaction per token
from Colony L1 to Splitter contract L1 (with executor reward)
EthereansOS Colony contract on L2
The following reported is the Colony L2 contract used by EthereansOS on Optimism. Consider it a guideline to build your own Colony L2 contract according to your needs.
The purpose of the contract is to receive tokens on Optimism and bridge them by interacting with the standard Optimism bridge.
The Colony
contract inherits abstractColony
and implements the IL2ERC20Bridge
and IL2StandardERC20
interfaces to interact with the standard Optimism bridge.
custom sendTokens logic
The contract provides an override of the virtual
_send
method (used internally by sendTokens
) provided by AbstractColony
in order to interact with the Optimism Bridge to bring tokens to L1:
In this first Colonies version, If there is an host
set different from address(0)
and if the msg.sender
of the sendTokens
method is the host
(EthereansOS deployer wallet) the tokens are sent to him who will bridge them.
If msg.sender
is other than the host
address , _transferToL1
is called which interacts with the standard Optimism bridge by bringing the tokens to L1 using the withdrawTo
method:
The address
to
passed to withdrawTo
is the receiverResolver
address previously initialized that is the address of the Colony L1 contract. In this way, tokens are moved from Colony L2 contract on Optimism to Colony L1 contract on Ethereum.
EthereansOS Colony contract on L1
The following reported is the Colony L1 contract used by EthereansOS on Ethereum. Consider it a guideline to build your own Colony L1 contract according to your needs.
The purpose of the contract is to receive tokens on Ethereum from the Optimism Bridge and send them to the EthereansOS Organization (L1).
Custom Initialization
The Colony
contract on L1 involves overriding the empty virtual
method _colonyLazyInit
to initialize an additional parameter decoding the lazyInitResponse
parameter:
tokenToBurnAddress
-> it represents the address of the token that is burned and not transferred whensendTokens
is called. In this case it is $OS.
custom sendTokens logic
The contract provides an override of the virtual
_send
method (used internally by sendTokens
) provided by AbstractColony
in order to burn $OS.
So all $OS bridged from Optimism to Ethereum via Colonies are burned by Colony L1 contract.
custom resolveReceiver
The contract provides an override of the virtual
resolveReceiver()
method provided by AbstractColony
setting the receiver address of the tokens (when sendTokens
is called) as the TreasurySplitter
address or possibly the treasuryManager
(if TreasurySplitter
is not retrievable) of EthereansOS Organization (L1).
Last updated