The Account.sol contract is meant to be a canonical instance, deployed once, and used by many instances of Proxy.sol via
delegatecallproxied function calls. It contains all logic for proxy account interactions.
The Account contract exposes 4 functions that allow state changes to proxy account instances:
Makes a function call from the account proxy to an external contract using the
callopcode. Can only be called directly by the proxy account owner. This function can be used to execute account actions that require calls to external contracts, such as an ERC20 transfer.
Makes a delegated function call from the account proxy to an external contract using the
delegatecallopcode. Can only be called directly by the proxy account owner. This function can be used to execute any call directly on the proxy account instance. It can be used to modify any state on the account. Practical examples of use include
sstoreexecution, outgoing ETH transfers, or direct execution of complex logic such as a swap on an AMM.
Allows execution of a
delegatecallpermitted by an EIP-712 message signed by the proxy account owner. Can be called by any address as long as a valid signed message is provided.
toaddress of a
metaDelegateCall()should be the address of a secure verifier contract (see brink-verifiers for examples). The
dataparameter contains the function call data to execute on the verifier contract. Both
datamust be included in the signed message.
Allows execution of a
delegatecallpermitted by an EIP-712 message signed by the proxy account owner, with additional unsigned call data provided by the transaction executor. Can be called by any address as long as a valid signed message is provided.
dataparameter behave the same way as they do in
unsignedDataparameter is provided by the transaction executor, and is not included as part of the signed message. It is appended to
dataand executed on the verifier contract at the
toaddress. The verifier must be set up to securely handle arbitrary execution of the unsigned portion of the call data it receives.
See the LimitSwapVerifier.tokenToToken() as an example of a verifier function that is designed to securely handle a partially signed delegate call. This function requires that the signed output, input, and expiry conditions are met, while allowing the executor to provide its own call data to source the limit swap.
The Proxy.sol contract is a gas-optimized proxy instance deployed for each Brink account owner. This contract contains no specific logic for accounts. It uses
fallback()function to execute logic from the
implementationaddress, which should be the canonical Account.sol address.
Brink proxies can be upgraded by owner by modifying the
implementationaddress at the storage location set by the
IMPLEMENTATION_PTRconstant. We recommend that you do not modify the implementation address! Your account will no longer be supported by any of the Brink open source tools such as brink-sdk.
See https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies for general info on the proxy upgrade pattern.
DeployAndCall.solcontract allows for contract deployment and execution of call data on the newly deployed contract in the same transaction. It is not Brink specific, but can be used by executors to conveniently execute meta transactions on undeployed Brink proxy accounts by batching deployment and call into a single transaction.
The CallExecutor.sol contract can be used by verifier functions to securely execute arbitrary call data without exposing the proxy account as
See an example of use in LimitSwapVerifier.tokenToToken(). If the arbitrary call data execution here was not proxied through CallExecutor, this verifier would unsafely allow execution of any external contract call directly from the account proxy instance. A malicious executor could use this to initiate a 3rd ERC20 transfer to their own address, after satisfying the verified swap conditions.
The brink-verifiers repo contains contracts for Brink account signed messages. Verifiers are used to verify valid conditions for order execution, and to execute state changes that fulfill the conditions of an order.
The LimitSwapVerifier.sol contract contains verifier functions for Brink limit swap orders. These are designed to be executed with
metaPartialDelegateCall()signed messages. The input, output, and expiry parameters are signed by account owners. Additional unsigned data is provided by the transaction executor to source the swap output.
Limit swap verifier functions are un-opinionated about how swaps are sourced. They will succeed as long as the required swap output is provided, and allow no more than the specified swap input to be transferred out of the account.
Note that the execution profit incentive for limit swaps is arbitrage based. The transaction executor can take a portion of input or output, as long as the verifier's requirements are met. There is a competitive incentive to source the swap efficiently, because a signed swap can only be executed once.
Supports ERC20 to ERC20 signed swaps.
Supports ETH to ERC20 signed swaps.
Supports ERC20 to ETH signed swaps.
The CancelVerifier.sol contract contains a verifier function that invalidates an existing signed message, effectively cancelling the order associated with it. It writes to a
bitmapIndexwhich will invalidated any message that requires this
bitmapIndexto be empty. This can be used to cancel LimitSwapVerifier signed swaps, or any signed message type for a verifier that shares the same replay protection storage location.
Note that there is no profit incentive for executors to cancel on an owner's behalf. CancelVerifier.cancel() is designed to be called directly by account owners using Account.delegateCall().