This is a modular proposal for the ERC20x EVM token Standard which extends ERC20.
Modules:
- Primitives:
- transfer to 1 (covered by ERC20. We add a variant which is allowed to invoke hooks)
- flow to 1
- transfer to n
- flow to n
- ACL: allow delegation to an operator. Arbitrary restrictions can be implemented by making the operator a contract.
- Hooks: Any account can designate any contract implementing a hook interface as handler. For 1 to n actions, only the pool manager can set up receive hooks.
interface IERC20xPrimitives is IERC20 {
/// Note: This overloads ERC20.transfer() and will invoke hooks.
function transfer(address to, uint256 amount, bytes data) returns (bool);
function flow(address to, uint256 flowRate, bytes data) returns (bool);
function transferToMany(IPool pool, uint256 amount, bytes data) returns (bool);
function flowToMany(IPool pool, uint256 flowRate, bytes data) returns (bool);
}
interface IERC20xACL {
function authorizeOperator(address operator);
function revokeOperator(address operator);
function isOperatorFor(address operator, address holder) view returns (bool);
function operatorTransfer(address to, uint256 amount, bytes data, bytes operatorData) returns (bool);
function operatorFlow(address to, uint256 flowRate, bytes data, bytes operatorData) returns (bool);
function operatorTransferToMany(IPool pool, uint256 amount, bytes data, bytes operatorData) returns (bool);
function operatorFlowToMany(IPool pool, uint256 flowRate, bytes data, bytes operatorData) returns (bool);
}
interface IPool is IERC20 {
/// has privileged access. Should be a contract.
function getManager() exernal view returns(address);
}
// HOOKS
// Inspired by ERC-777: any account (incl. EOAs) can set up hooks,
// the hook logic is not tied to the sender/receiver.
// Thus EOAs can also set up hooks, and a hook implementation can be shared by many.
interface IERC20xHooks {
function getHookHandlerRegistry() view returns(address);
// Note: returns 0 if not supported
function getReceiveHookGasLimit() view returns(uint256);
function getACLSendHookGasLimit() view returns(uint256);
function getACLReceiveHookGasLimit() view returns(uint256);
}
interface IHookHandlerRegistry {
/// msg.sender sets up a hook handler (contract) for themselves. handlerAddress zero resets.
function setHookHandler(bytes32 hookTypeHash, address handlerAddress);
}
interface IERC20xReceiveHook {
function onTransferReceive(address from, address to, uint256 amount, bytes data);
function onFlowReceive(address from, address to, uint256 flowRate, uint256 prevFlowRate, bytes data);
/// can only be set up by pool managers
function onTransferToManyReceive(address from, IPool to, uint256 amount, bytes data);
/// can only be set up by pool managers
function onFlowToManyReceive(address from, address IPool, uint256 flowRate, uint256 prevFlowRate, bytes data);
}
// HOOKS for ACL actions
/// Send hooks can be useful together with ACL to enforce arbitrary and dynamic restrictions on operator actions.
interface IERC20xACLSendHook {
function onTransferSend(address operator, address from, address to, uint256 amount, bytes data, bytes operatorData);
function onFlowSend(address operator, address from, address to, uint256 flowRate, uint256 prevFlowRate, bytes data, bytes operatorData);
function onTransferToManySend(address operator, address from, IPool to, uint256 amount, bytes data, bytes operatorData);
function onFlowToManySend(address operator, address from, address IPool, uint256 flowRate, uint256 prevFlowRate, bytes data, bytes operatorData);
}
interface IERC20xACLReceiveHook {
function onTransferReceive(address operator, address from, address to, uint256 amount, bytes data, bytes operatorData);
function onFlowReceive(address operator, address from, address to, uint256 flowRate, uint256 prevFlowRate, bytes data, bytes operatorData);
/// can only be set up by pool managers
function onTransferToManyReceive(address operator, address from, IPool to, uint256 amount, bytes data, bytes operatorData);
/// can only be set up by pool managers
function onFlowToManyReceive(address operator, address from, address IPool, uint256 flowRate, uint256 prevFlowRate, bytes data, bytes operatorData);
}