SwiftGate contracts
Swift Gate - 0xB84f07612F4bfEc42E042b6CDD26df496b3d397f
The swift gate smart contract is responsible for bridging tokens between different blockchains. The governors whitelist tokens on a certain chain id that can be bridged to other chain ids.
Users call swiftSend()
to bridge tokens to other chain and specify if they want the swiftReceive()
call on the destination chain to be batched with other users bridged tokens or not. Calling swiftSend()
with the isSingle_
argument to true will inccur in much bigger gas costs, but instant bridging, whereas setting this flag to false is slower but about 6 times cheaper.
The governors, each running the backend, sign a transaction specifying tokens to be received on the destination chain after users call swiftSend()
in the source chain.
Validating 13 signatures is an expensive process and to compensate for this, swift gate leverages batching user deposits so that for a batch of bridged tokens only a message hash has to be signed. For example, for each bridged token, a regular bridge would require 2 transactions, one on the source chain and one on the destination chain, having to validate 13 signatures once. In this case, for 10 deposits, it would require 20 transactions in which the signatures are validated 10 times. However, if the bridged assets are batched, it takes 11 transactions (10 swiftSend()
+ 1 swiftReceive()
) and the signatures are only validate once.
The governors are rewarded with yield from depositing the bridged assets into Aave. They can call functions depositToAave()
and withdrawFromAave()
to claim their rewards.
Token Factory - 0xDBAF1e8f67B63a1DA2f9bB0214d6087cAA58170D
The token factory creates wrapped tokens for tokens on other blockchains. Its owner is the swift gate, from which governors can create new wrapped tokens.
The tokens are clones, which means that they have a common implementation as SwiftERC20
. When a token is created on the token factory, it deploys a proxy which points to the implementation, effectively reducing gas costs significantly for the governors.
SwiftERC20 - 0x46972365C218484d1286B6Ea08d35bD5aaa935C4
Implementation of wrapped tokens of the swift gate. Regular ERC20 token that is mintable and burnable by the swift gate. When a token not native to a blockchain is received, the receiver is minted wrapped tokens. When the user wants to bridge back the tokens, these are burned and they get the remote tokens on the original blockchain.
Smart Contracts Architecture
SwiftERC20
Inherits: ERC20Upgradeable
State Variables
_swiftGate
address of the swift gate contract
address internal _swiftGate;
_remoteToken
address of the remote token contract
address internal _remoteToken;
Functions
onlySwiftGate
can only be called by swift gate
modifier onlySwiftGate();
initialize
initialize the contract
function initialize(string memory name_, string memory symbol_, address swiftGate_, address remoteToken_)
public
initializer;
Parameters
Name | Type | Description |
---|---|---|
name_ | string | name of the wrapped token |
symbol_ | string | symbol of the wrapped token |
swiftGate_ | address | address of the swift gate contract |
remoteToken_ | address | address of the remote token contract |
mint
swift gate mints tokens
function mint(address account_, uint256 amount_) external onlySwiftGate;
Parameters
Name | Type | Description |
---|---|---|
account_ | address | address to mint tokens to |
amount_ | uint256 | amount of tokens to mint |
burn
swift gate burns tokens
function burn(address account_, uint256 amount_) external onlySwiftGate;
Parameters
Name | Type | Description |
---|---|---|
account_ | address | address to burn tokens from |
amount_ | uint256 | amount of tokens to burn |
getSwiftGate
returns the address of the swift gate
function getSwiftGate() external view returns (address);
getRemoteToken
returns the address of the remote token
function getRemoteToken() external view returns (address);
Errors
OnlySwiftGateError
triggered when an address other than the swift gate calls this contract
error OnlySwiftGateError(address msgSender_);
SwiftGate
State Variables
_chainId
chain id of swift gate on this chain
uint16 internal _chainId;
_aaveV3LendingPool
Aave v3 lending pool
IPool internal _aaveV3LendingPool;
_aaveV3RewardsController
Aave v3 rewards controller
IRewardsController internal _aaveV3RewardsController;
_governors
Mapping of governor address => is governor
mapping(address => bool) internal _governors;
_feeOfChainId
Mapping of chainId => fee
mapping(uint256 => uint256) internal _feeOfChainId;
_feeIfBatchedOfChainId
Mapping of chainId => fee if batched
mapping(uint256 => uint256) internal _feeIfBatchedOfChainId;
_signedMessages
Mapping of chainId => is chain supported
mapping(bytes32 => bool) internal _signedMessages;
_remoteToWrappedTokens
Mapping of chainId => destination token => wrappedToken
mapping(uint256 => mapping(address => address)) internal _remoteToWrappedTokens;
_wrappedToRemoteTokens
Mapping of token to wrapped token
mapping(address => address) internal _wrappedToRemoteTokens;
_dstTokens
Mapping of chainId => local token => is supported token
mapping(uint256 => mapping(address => bool)) internal _dstTokens;
_tokenFactory
Factory for creating wrapped tokens
TokenFactory internal immutable _tokenFactory;
_minSignatures
Minimum signatures to validate messages
uint256 internal _minSignatures;
Functions
constructor
creates the TokenFactory which is owner by this contract - swift gate
constructor();
initialize
initializes the swift gate contract
function initialize(
uint16 chainId_,
address aaveV3,
address aaveV3RewardsController_,
address[] memory governors_,
uint256 minSignatures_
) external;
Parameters
Name | Type | Description |
---|---|---|
chainId_ | uint16 | chain id of the swift gate contract |
aaveV3 | address | aave v3 lending pool address |
aaveV3RewardsController_ | address | aave v3 rewards controller address |
governors_ | address[] | array of governor addresses |
minSignatures_ | uint256 | minimum number of signatures to validate messages |
swiftReceive
receives a batch of tokens, mints the wrapped versions and verifies the signatures.
function swiftReceive(SwReceiveParams[] calldata params_, Signature[] calldata signatures_, bytes32 salt_) external;
Parameters
Name | Type | Description |
---|---|---|
params_ | SwReceiveParams[] | struct with the parameters to sned across bridges - includes token, amount, receiver, srcChain, dstChain |
signatures_ | Signature[] | array of signatures from the governors (message hash signed by governors ) |
salt_ | bytes32 | salt used to enable signing the same message more than once |
swiftSend
sends a token to another chain.
function swiftSend(address token_, uint256 amount_, address receiver_, uint16 dstChain_, bool isSingle_) external;
Parameters
Name | Type | Description |
---|---|---|
token_ | address | the token to send. |
amount_ | uint256 | the amount of tokens to send. |
receiver_ | address | the receiver of the tokens. |
dstChain_ | uint16 | the destination chain. |
isSingle_ | bool | whether the token is to be batched with other tokens to save gas or not. |
addWrappedToken
adds a wrapped token to the respective mapping so it can be used across chains
function addWrappedToken(
uint16 chainId_,
address token_,
string memory name_,
string memory symbol_,
Signature[] calldata signatures_,
bytes32 salt_
) external;
Parameters
Name | Type | Description |
---|---|---|
chainId_ | uint16 | chain id of the wrapped token |
token_ | address | token that is being wrapped |
name_ | string | name of the wrapped token |
symbol_ | string | symbol of the wrapped token |
signatures_ | Signature[] | array of signatures from the governors (message hash signed by governors ) |
salt_ | bytes32 | salt used to enable signing the same message more than once |
addDstToken
Adds a token to the dstTokens mapping (verified with the signatures). Signals that a token can be bridged to another chain
function addDstToken(uint16 chainId_, address token_, Signature[] calldata signatures_, bytes32 salt_) external;
Parameters
Name | Type | Description |
---|---|---|
chainId_ | uint16 | chain id of the token |
token_ | address | token that is being added |
signatures_ | Signature[] | array of signatures from the governors (message hash signed by governors ) |
salt_ | bytes32 | salt used to enable signing the same message more than once |
depositToAaveV3
deposits a given token in the aave lending pool
function depositToAaveV3(address token_, uint256 amount_, Signature[] calldata signatures_, bytes32 salt_) external;
Parameters
Name | Type | Description |
---|---|---|
token_ | address | token to be deposited |
amount_ | uint256 | amount to be deposited |
signatures_ | Signature[] | array of signatures from the governors (message hash signed by governors ) |
salt_ | bytes32 | salt used to enable signing the same message more than once |
withdrawFromAaveV3
withdraws tokens and rewards from aave to claim the yield for the governors
function withdrawFromAaveV3(
address token_,
address aToken_,
uint256 amount_,
address receiver_,
Signature[] calldata signatures_,
bytes32 salt_
) external;
Parameters
Name | Type | Description |
---|---|---|
token_ | address | token to be withdrawn |
aToken_ | address | corresponding aave token. Required for the rewards controller |
amount_ | uint256 | amount to be withdrawn |
receiver_ | address | address to receive the tokens |
signatures_ | Signature[] | array of signatures from the governors (message hash signed by governors ) |
salt_ | bytes32 | salt used to enable signing the same message more than once |
setFeeOfChainId
sets the fee for a given chain id
function setFeeOfChainId(uint16 chainId_, uint256 fee_, Signature[] calldata signatures_, bytes32 salt_) external;
Parameters
Name | Type | Description |
---|---|---|
chainId_ | uint16 | chain id to set the fee for |
fee_ | uint256 | fee to be set |
signatures_ | Signature[] | array of signatures from the governors (message hash signed by governors ) |
salt_ | bytes32 | salt used to enable signing the same message more than once |
setFeeIfBatchedOfChainId
sets the fee if the swiftSend call is batched for a given chain id. Much cheaper than single fee
function setFeeIfBatchedOfChainId(
uint16 chainId_,
uint256 feeIfBatched_,
Signature[] calldata signatures_,
bytes32 salt_
) external;
Parameters
Name | Type | Description |
---|---|---|
chainId_ | uint16 | chain id to set the fee for |
feeIfBatched_ | uint256 | fee to be set |
signatures_ | Signature[] | array of signatures from the governors (message hash signed by governors ) |
salt_ | bytes32 | salt used to enable signing the same message more than once |
setGovernors
sets the governors of the swift gate. Useful if governors are not working well and need to be replaced
function setGovernors(
address[] calldata governors_,
bool[] calldata set_,
Signature[] calldata signatures_,
bytes32 salt_
) external;
Parameters
Name | Type | Description |
---|---|---|
governors_ | address[] | array of governors to be set |
set_ | bool[] | array of booleans to set the governors to true or false |
signatures_ | Signature[] | array of signatures from the governors (message hash signed by governors ) |
salt_ | bytes32 | salt used to enable signing the same message more than once |
setMinSignatures
sets the min signatures required to execute calls to the swift gate
function setMinSignatures(uint256 minSignatures_, Signature[] calldata signatures_, bytes32 salt_) external;
Parameters
Name | Type | Description |
---|---|---|
minSignatures_ | uint256 | min signatures to be set |
signatures_ | Signature[] | array of signatures from the governors (message hash signed by governors ) |
salt_ | bytes32 | salt used to enable signing the same message more than once |
getFeeOfChainId
gets the single swift send fee of to a given chain id
function getFeeOfChainId(uint16 chainId_) external view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
chainId_ | uint16 | chain id to get the fee for |
getFeeIfBatchedOfChainId
gets the batched swift send fee of to a given chain id
function getFeeIfBatchedOfChainId(uint16 chainId_) external view returns (uint256);
Parameters
Name | Type | Description |
---|---|---|
chainId_ | uint16 | chain id to get the fee for |
getChainId
gets the chain id of the swift gate
function getChainId() external view returns (uint256);
isGovernor
checks if an account is a governor
function isGovernor(address account_) external view returns (bool);
Parameters
Name | Type | Description |
---|---|---|
account_ | address | account to check |
Returns
Name | Type | Description |
---|---|---|
<none> | bool | true if the account is a governor, false otherwise |
getWrappedToken
gets the wrapped token of a given chain id and token address
function getWrappedToken(uint16 chainId_, address token_) external view returns (address);
Parameters
Name | Type | Description |
---|---|---|
chainId_ | uint16 | chain id to get the wrapped token for |
token_ | address | token to get the wrapped token for |
Returns
Name | Type | Description |
---|---|---|
<none> | address | wrapped token address |
getTokenFactory
gets the token factory address that creates the wrapped tokens
function getTokenFactory() external view returns (address);
Returns
Name | Type | Description |
---|---|---|
<none> | address | token factory address |
getRemoteTokenOf
gets the remote token of a given wrapped token address
function getRemoteTokenOf(address wrappedToken_) external view returns (address);
Parameters
Name | Type | Description |
---|---|---|
wrappedToken_ | address | wrapped token to get the remote token for |
Returns
Name | Type | Description |
---|---|---|
<none> | address | remote token address |
isDstToken
checks if a token is allowed to be bridged to a destination chain id
function isDstToken(uint16 chainId_, address token_) external view returns (bool);
Parameters
Name | Type | Description |
---|---|---|
chainId_ | uint16 | chain id to check |
token_ | address | token to check |
Returns
Name | Type | Description |
---|---|---|
<none> | bool | true if the token is allowed to be bridged, false otherwise |
getMinSignatures
gets the min signatures required to execute calls to the swift gate
function getMinSignatures() external view returns (uint256);
getAaveV3LendingPool
gets the aave v3 lending pool address
function getAaveV3LendingPool() external view returns (address);
_verifySignatures
function _verifySignatures(bytes32 messageHash_, Signature[] calldata signatures_) internal;
Events
SwiftSend
emitted when an account calls swiftSend and bridges to the destination chain
event SwiftSend(address token, address remoteToken_, uint256 amount, address receiver, uint16 dstChain, bool isSingle);
Errors
LengthMismatchError
triggered when the lengths of the array arguments don't match
error LengthMismatchError();
NotEnoughSignaturesError
triggered when the number of signatures is less than the minimum
error NotEnoughSignaturesError();
InvalidSignatureError
triggered when the signature is invalid
error InvalidSignatureError();
WrontDstChainError
error WrontDstChainError(uint256 chainId);
UnsupportedTokenError
triggered when the token is not supported on a certain destination chain
error UnsupportedTokenError(uint16 chainId, address token);
ZeroAddressError
triggered on a zero address argument
error ZeroAddressError();
ZeroAmountError
triggered when the amount is zero
error ZeroAmountError();
ChainIdAlreadySetError
triggered when the chain id is already set. Prevents reinitialization
error ChainIdAlreadySetError();
DuplicateSignatureError
triggered when the signature is a duplicate. Prevents message replay
error DuplicateSignatureError();
Structs
Signature
Struct to hold signature data
struct Signature {
uint8 v;
bytes32 r;
bytes32 s;
}
SwReceiveParams
Struct to hold swift receive parameters
struct SwReceiveParams {
address token;
uint256 amount;
address receiver;
uint16 srcChain;
uint16 dstChain;
}
TokenFactory
State Variables
_implementation
implementation of the swiftGate wrapped tokens
address internal immutable _implementation;
_swiftGate
address of the swift gate contract
address internal immutable _swiftGate;
Functions
onlySwiftGate
can only be called by swift gate
modifier onlySwiftGate();
constructor
the swift gate creates the token factory in its constructor.
constructor();
create
create a new wrapped token. Called by the swift gate
function create(string memory name_, string memory symbol_, address remoteToken_)
external
onlySwiftGate
returns (address proxy_);
Parameters
Name | Type | Description |
---|---|---|
name_ | string | name of the wrapped token |
symbol_ | string | symbol of the wrapped token |
remoteToken_ | address | address of the remote token contract |
getImplementation
returns the address of the implementation of the wrapped tokens
function getImplementation() external view returns (address);
Errors
OnlySwiftGateError
triggered when an address other than the swift gate calls this contract
error OnlySwiftGateError(address msgSender_);