923 lines
30 KiB
Markdown
923 lines
30 KiB
Markdown
# Smart contract interfaces
|
||
|
||
## Technology
|
||
|
||
CIC smart contracts are implemented using the *solidity* programming
|
||
language for the (Ethereum Virtual Machine (EVM).
|
||
|
||
## Adopted standards
|
||
|
||
### Signing
|
||
|
||
### ERC - Direct use
|
||
|
||
The following well-known solidity interfaces are used directly.
|
||
|
||
- [ERC20 - Token Standard](https://eips.ethereum.org/EIPS/eip-20)
|
||
|
||
- [ERC165 - Standard Interface
|
||
Detection](https://eips.ethereum.org/EIPS/eip-165)
|
||
|
||
- [ERC173 - Contract Ownership
|
||
Standard](https://eips.ethereum.org/EIPS/eip-173)
|
||
|
||
- [ERC191 - Signed Data
|
||
Standard](https://eips.ethereum.org/EIPS/eip-191)
|
||
|
||
- [ERC712 - Typed structured data hashing and
|
||
signing](https://eips.ethereum.org/EIPS/eip-712)
|
||
|
||
- [ERC721 - Non-Fungible Token
|
||
Standard](https://eips.ethereum.org/EIPS/eip-721)
|
||
|
||
- [ERC5007 - Time NFT (EIP-721 Time
|
||
Extension)](https://eips.ethereum.org/EIPS/eip-5007)
|
||
|
||
- [ERC5192 - Minimal Soulbound
|
||
NFTs](https://eips.ethereum.org/EIPS/eip-5192)
|
||
|
||
### ERCs Partial use
|
||
|
||
The following well-known solidity interfaces are partially implemented
|
||
in CIC native interfaces.
|
||
|
||
- [ERC5679 - Token Minting and
|
||
Burning](https://eips.ethereum.org/EIPS/eip-5679) (See `Minter`,
|
||
`Burner`)
|
||
|
||
## Native interfaces
|
||
|
||
### Accounts Index
|
||
|
||
Append-only list of addresses. Typically used for access control lists.
|
||
|
||
Addresses may be *added*, *removed*, aswell as *deactivated* and
|
||
*activated*. Deactivated accounts still count towards the `entryCount`.
|
||
|
||
The `entry` method is used to iterate the account list. The order of
|
||
which accounts are returned is not guaranteed. Any returned value
|
||
matching `address(0x00)` should be skipped, and not counted towards
|
||
`entryCount`.
|
||
|
||
May optionally record time when account was added.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
b7bca625
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface IAccountsIndex {
|
||
// Address added to store, index in array.
|
||
event AddressAdded(uint256 indexed _idx, address _account);
|
||
|
||
// Return number of entries in index.
|
||
function entryCount() external view returns (uint256);
|
||
|
||
// Return entry at the spceificed index.
|
||
// Will revert if index is beyond array length.
|
||
// An entry result of 0 means the entry should be skipped, and not count towards entry count.
|
||
function entry(uint256) external view returns (address);
|
||
|
||
// Add an entry to the index. Incresases the entry count.
|
||
function add(address) external returns (bool);
|
||
|
||
// Verify that the entry exists in the index.
|
||
function have(address) external view returns (bool);
|
||
|
||
// Retrieve the timestamp when account was added.
|
||
// If time is not being tracked, a value of 0 should be returned.
|
||
function time(address) external view returns (uint256);
|
||
}
|
||
|
||
#### Reference implementation
|
||
|
||
<git://holbrook.no/eth-accounts-index.git> (v0.5.1)
|
||
|
||
### Accounts Index Mutable
|
||
|
||
Extends the functionality of `Accounts Index` to allow changes to the
|
||
address list.
|
||
|
||
Addresses may be *added*, *removed*, aswell as *deactivated* and
|
||
*activated*. Deactivated accounts still count towards the `entryCount`.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
9479f0ae
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface IAccountsIndexMutable {
|
||
// Active status of address changed, and by whom changed.
|
||
event AddressActive(address indexed _account, bool _active);
|
||
|
||
// Address removed from store, and by whom removed.
|
||
event AddressRemoved(address _account);
|
||
|
||
// Remove an entry from the index. Reduces the entry count.
|
||
function remove(address) external returns (bool);
|
||
|
||
// Deactivate account but keep in index. Does not affect entry count.
|
||
function deactivate(address) external returns (bool);
|
||
|
||
// Activate previously deactivated account. Does not affect entry count.
|
||
function activate(address) external returns (bool);
|
||
|
||
// Check if account exists and is active;
|
||
function isActive(address) external view returns (bool);
|
||
}
|
||
|
||
#### Reference implementation
|
||
|
||
<git://holbrook.no/eth-accounts-index.git> (v0.5.1)
|
||
|
||
### Burner
|
||
|
||
Attached to `ERC20` and `ERC721` tokens that may be *burned*.
|
||
|
||
Implements the `burn(...)` part of `ERC5679` for interoperability.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
b1110c1b
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface IBurner {
|
||
// Token(s) successfully burned; by who and how much.
|
||
event Burn(address indexed _burner, uint256 _burned);
|
||
|
||
// Satisfies ERC 5679
|
||
function burn(address _from, uint256 _amount, bytes calldata _data) external;
|
||
|
||
// Burn given amount of tokens held by signer.
|
||
function burn(uint256 _amount) external returns (bool);
|
||
|
||
// Burn all tokens held by signer.
|
||
// Returns the amount of tokens burned.
|
||
function burn() external returns (uint256);
|
||
|
||
// Total amount of tokens that have been burned.
|
||
function totalBurned() external returns (uint256);
|
||
|
||
// Total amount of tokens ever minted.
|
||
// If totalSupply() is available (ERC20, ERC721 Enumerable), this equals totalSupply() + totalBurned().
|
||
function totalMinted() external returns (uint256);
|
||
}
|
||
|
||
#### Example implementation
|
||
|
||
<https://git.grassecon.net/cicnet/erc20-demurrage-token.git>
|
||
|
||
### Chrono
|
||
|
||
Define a creation time for a resource.
|
||
|
||
Complements `ERC5007`.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
4db1ccd4
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface IChrono {
|
||
// Returns the timestamp of when a resource corresponding to _idx was first created.
|
||
// int64 chosen as return value for simpler interoperability with ERC5007.
|
||
function createTime(uint256 _idx) external returns(int64);
|
||
}
|
||
|
||
#### Example implementation
|
||
|
||
<https://git.defalsify.org/eth-erc721> (BadgeToken contract)
|
||
|
||
### Declarator
|
||
|
||
Permissionless store of signed claims made by an address about other
|
||
addresses, or addresses about themselves.
|
||
|
||
It is used to declare or respond to certifications of vouchers, NFT,
|
||
voucher members.
|
||
|
||
Addresses may be Externally Owned Accounts or smart contracts.
|
||
|
||
Claims may be made with or without topics. A missing topic is synonymous
|
||
with a topic value of `bytes32(0x00)`.
|
||
|
||
Any number of claims can be made about an address under any number of
|
||
topics. All claims must be stored, and returned in the order which they
|
||
were added.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
21b7493b
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface IDeclarator {
|
||
event DeclarationAdded(address indexed _declarator, address indexed _subject, bytes32 indexed _topic, bytes32 _proof);
|
||
|
||
// Get all declarations for a subject (without topic) signed by a declarator
|
||
function declaration(address _declarator, address _subject) external view returns ( bytes32[] memory );
|
||
|
||
// Get all declarations for a subject for the given topic signed by a declarator
|
||
function declaration(address _declarator, address _subject, bytes32 _topic) external view returns ( bytes32[] memory );
|
||
|
||
// Get number of declarations the declarator has ever signed
|
||
function declarationCount(address _declarator) external view returns ( uint256 );
|
||
|
||
// Get the subject of a declarator's declarations at the specific index
|
||
function declarationAddressAt(address _declarator, uint256 _idx) external view returns ( address );
|
||
|
||
// Add a declaration for the subject
|
||
function addDeclaration(address _subject, bytes32 _proof) external returns ( bool );
|
||
|
||
// Add a declaration with topic for the subject
|
||
function addDeclaration(address _subject, bytes32 _proof, bytes32 _topic) external returns ( bool );
|
||
|
||
// Get the declarator that signed a declaration at the specificed index for a subject
|
||
function declaratorAddressAt(address _subject, uint256 _idx) external view returns ( address );
|
||
|
||
// Get the number of declarators that have signed for a subject
|
||
function declaratorCount(address _subject) external view returns ( uint256 );
|
||
}
|
||
|
||
#### Reference implementation
|
||
|
||
<git://holbrook.no/eth-address-index.git>
|
||
|
||
### Digest
|
||
|
||
Allows encoding of digests according to a specific encoding scheme.
|
||
|
||
Primary use-case is the abstraction of self-describing
|
||
[Multhash](https://multiformats.io/multihash/) encoding.
|
||
|
||
A default encoding *must* always be defined, and the encoding of a valid
|
||
digest *must* succeed with the default encoding.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
982ab05d
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface IDigest {
|
||
// Returns the default digest encoding used by the contract instance.
|
||
function defaultDigestEncoding() external view returns (uint256 _encoding);
|
||
|
||
// Check if the given encoding has been implemented in the contract instance.
|
||
function haveDigestEncoding(uint256 _codec) external view returns(bool);
|
||
|
||
// Verify and encode the given digest for a specific hashing algorithm.
|
||
// Returns a zero-length byte array if digest is invalid.
|
||
// Must succeed if called with the defaultDigestEncoding and a valid digest.
|
||
function encodeDigest(bytes memory _data, uint256 _encoding) external view returns (bytes memory);
|
||
|
||
// Encodes the digest using the default digest encoding.
|
||
// Returns a zero-length byte array if digest is invalid.
|
||
// Must succeed with a valid digest.
|
||
function encodeDigest(bytes memory _data) external view returns (bytes memory);
|
||
}
|
||
|
||
#### Example implementation
|
||
|
||
<git://holbrook.no/eth-event-msg.git>
|
||
|
||
### Expire
|
||
|
||
Defines an expiry time after which token balances and supply *cannot
|
||
change*.
|
||
|
||
A contract defining an expiry *must not* allow changing the expiration
|
||
time to a time in the past.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
841a0e94
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface IExpire {
|
||
// Contract has expired.
|
||
event Expired(uint256 _timestamp);
|
||
|
||
// Expiry time has changed.
|
||
event ExpiryChange(uint256 indexed _oldTimestamp, uint256 _newTimestamp);
|
||
|
||
// The current expiration timestamp.
|
||
function expires() external returns (uint256);
|
||
|
||
// Check expiry and apply expiration if expired.
|
||
// Return values must be:
|
||
// 0: not yet expired.
|
||
// 1: already expired.
|
||
// >1: expiry executed.
|
||
function applyExpiry() external returns(uint8);
|
||
}
|
||
|
||
#### Example implementation
|
||
|
||
<https://git.grassecon.net/cicnet/erc20-demurrage-token.git>
|
||
|
||
### Faucet
|
||
|
||
Used for dispensing tokens to any address.
|
||
|
||
It can be used for gas tokens and *ERC20* alike.
|
||
|
||
The interface is the same whether the faucet is dispensing from existing
|
||
balance or minting new tokens.
|
||
|
||
The value dispersed *must* be the same for all addresses.
|
||
|
||
In general, four criteria are expected to exist in any combination for
|
||
limiting access to the faucet:
|
||
|
||
Time
|
||
A recipient may only use the faucet again after some time has passed.
|
||
|
||
Balance threshold
|
||
A recipient may only use the faucet after its balance is below a certain
|
||
amount.
|
||
|
||
Membership
|
||
A recipient may only use the faucet if it has been added to an access
|
||
control list.
|
||
|
||
Capacity
|
||
The contract has sufficient token funds to dispense the current defined
|
||
amount to dispense.
|
||
|
||
The *check(address)* contract call *must* evaluate all four criteria,
|
||
and *must* return `false` if any of the criteria are not met.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
1a3ac634
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface IFaucet {
|
||
// Tokens were given to an address
|
||
event Give(address indexed _recipient, address indexed _token, uint256 _value);
|
||
|
||
// The amount that the faucet disperses has changed
|
||
event FaucetAmountChange(uint256 _value);
|
||
|
||
// Address of token the faucet represents
|
||
// The faucet will return gas tokens with the zero-address is returned.
|
||
function token() external returns (address);
|
||
|
||
// Amount of tokens the faucet gives out
|
||
function tokenAmount() external returns (uint256);
|
||
|
||
// Give tokens to the given recipient. Returns amount of tokens given.
|
||
function giveTo(address _recipient) external returns (uint256);
|
||
|
||
// Give tokens to yourself. Returns amount of tokens given.
|
||
function gimme() external returns (uint256);
|
||
|
||
// Check if faucet may be used in the current contract state by _recipient
|
||
function check(address _recipient) external view returns (bool);
|
||
|
||
// Returns timestamp when faucet may be used again by _recipient
|
||
// If 0 is returned, the address has not yet been used.
|
||
// A return value of max(uint256) indicates that the faucet may not be used again.
|
||
function nextTime(address _recipient) external returns (uint256);
|
||
|
||
// Returns the token balance under which faucet may be used again by _recipient
|
||
// A return value of max(uint256) indicates that the faucet may be used regardless
|
||
// of the token balance of _recipient
|
||
function nextBalance(address _recipient) external returns (uint256);
|
||
}
|
||
|
||
#### Reference implementations
|
||
|
||
- <git://holbrook.no/erc20-faucet.git>
|
||
|
||
- <git://holbrook.no/eth-faucet.git>
|
||
|
||
### Locator
|
||
|
||
This interface supports `ERC721 Metadata`, in particular the
|
||
`tokenURI(uint256)` call.
|
||
|
||
Off-chain resources in the CIC network *must* be defined in terms of
|
||
content addressed strings.
|
||
|
||
It *must* be possible to refer to all off-chain resources directly by
|
||
the content address.
|
||
|
||
Furthermore, it *should* be possible to refer to a resource by a
|
||
fully-qualified location on the web or an overlay network (e.g. tor).
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
ed75b333
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface ILocator {
|
||
// URI that may or may not point to a specific resource location.
|
||
function toURI(bytes memory _data) external view returns (string memory);
|
||
|
||
// URL pointing to a specific resource location.
|
||
function toURL(bytes memory _data) external view returns(string memory);
|
||
}
|
||
|
||
#### Example implementation
|
||
|
||
<git://holbrook.no/eth-event-msg.git>
|
||
|
||
#### Expressing locators in terms of numeric token id
|
||
|
||
Given the numeric token id `1234567890987654321` (`0x112210f4b16c1cb1`
|
||
hex), and a base url `https://contentgateway.grassecon.net`, the result
|
||
of the methods may be as follows:
|
||
|
||
`toURI(toHex(1234567890987654321))`
|
||
-\>
|
||
`https://contentgateway.grassecon.net/000000000000000000000000000000000000000000000000112210f4b16c1cb1`
|
||
|
||
`toURL(toHex(1234567890987654321))`
|
||
-\>
|
||
`https://contentgateway.grassecon.net/000000000000000000000000000000000000000000000000112210f4b16c1cb1`
|
||
|
||
`tokenURI(1234567890987654321)`
|
||
-\>
|
||
`https://contentgateway.grassecon.net/000000000000000000000000000000000000000000000000112210f4b16c1cb1`
|
||
|
||
#### Expressing locators in terms of a digest
|
||
|
||
Given the data `foo`, the digest algorithm `sha256` and a base url
|
||
`https://contentgateway.grassecon.net`, the result of the methods may be
|
||
as follows:
|
||
|
||
`toURI(sha256(foo))`
|
||
-\>
|
||
`"sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"`
|
||
|
||
`toURL(sha256(foo))`
|
||
-\>
|
||
`"https://contentgateway.grassecon.net/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"`
|
||
|
||
`tokenURI(toUint(sha256(foo)))`
|
||
-\>
|
||
`"https://contentgateway.grassecon.net/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"`
|
||
|
||
#### Locator without URL
|
||
|
||
Given the data `foo`, the digest algorithm `sha256` and no base url, the
|
||
result of the methods may be as follows:
|
||
|
||
`toURI(sha256(foo))`
|
||
-\>
|
||
`"sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"`
|
||
|
||
`toURL(sha256(foo))`
|
||
-\> `""`
|
||
|
||
`tokenURI(toUint(sha256(foo)))`
|
||
-\>
|
||
`"sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"`
|
||
|
||
### Minter
|
||
|
||
Attached to `ERC20` and `ERC721` tokens that may be minted.
|
||
|
||
Implements the `mint(...)` and `safeMint(...)` parts of `ERC5679` for
|
||
interoperability.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
5878bcf4
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface IMinter {
|
||
// Tokens are successfully minted; by who, to whom and how much
|
||
event Mint(address indexed _minter, address indexed _beneficiary, uint256 value);
|
||
|
||
// The given token has been successfully minted; by who, to whom and how much
|
||
event Mint(address indexed _minter, address indexed _beneficiary, address indexed _token, uint256 value);
|
||
|
||
// Mint the specified value of tokens to the specified recipient
|
||
function mintTo(address _beneficiary, uint256 value) external returns (bool);
|
||
|
||
// Satisfies ERC5679 for ERC20
|
||
function mint(address _beneficiary, uint256 value, bytes calldata _data) external;
|
||
|
||
// Satisfies ERC5679 for ERC721
|
||
function safeMint(address _beneficiary, uint256 value, bytes calldata _data) external;
|
||
}
|
||
|
||
#### Example implementation
|
||
|
||
<https://git.grassecon.net/cicnet/erc20-demurrage-token.git>
|
||
|
||
### Msg
|
||
|
||
Enables a reference "message" to describe the contract using an
|
||
off-chain resource.
|
||
|
||
The reference may or may not be mutable.
|
||
|
||
The interface complements `Locator` and `MultiHash` to generate locators
|
||
for how to resolve the reference.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
a3002595
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface IMsg {
|
||
// Emitted when a new message digest has been set
|
||
// Should not be emitted if the digest set is identical to the previous
|
||
event Msg(bytes _msgDigest);
|
||
|
||
// Get the current message content hash
|
||
function getMsg() external view returns(bytes memory);
|
||
}
|
||
|
||
#### Example implementation
|
||
|
||
<git://holbrook.no/eth-event-msg.git>
|
||
|
||
### Registry
|
||
|
||
The Registry interface is a key-value store resolving well-known
|
||
contract identifier names to contract addresses.
|
||
|
||
It currently has two distinct uses in the CIC context:
|
||
|
||
1. Entry-point to discover all relevant contracts of CIC networks.
|
||
|
||
2. Unique (ERC20) token symbol resolver.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
effbf671
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface IRegistryClient {
|
||
// Address added to store with the given key
|
||
event AddressKey(bytes32 indexed _key, address _address);
|
||
|
||
// Return the address of the contract identified by the given byte string
|
||
function addressOf(bytes32) external view returns (address);
|
||
|
||
// Indexed accessor for the full list of registred identifiers
|
||
function identifier(uint256) external view returns (bytes32);
|
||
|
||
// Number of registered interfaces
|
||
function identifierCount() external view returns (uint256);
|
||
}
|
||
|
||
#### Contract registry implementation
|
||
|
||
<git://holbrook.no/eth-contract-registry.git>
|
||
|
||
#### Token index implementation
|
||
|
||
<git://holbrook.no/eth-contract-registry.git>
|
||
|
||
### Seal
|
||
|
||
Some smart contract parameters may need to be mutable over part of a
|
||
smart contract’s lifetime.
|
||
|
||
This interface provides a method to explicitly signal when certain
|
||
parameters have been rendered immutable.
|
||
|
||
The value of `sealState()` *must not* decrease, and must not exceed
|
||
`maxSealState`.
|
||
|
||
`maxSealState` is used to define that *all mutable parameters* have been
|
||
rendered immutable. The practical implications of this will vary between
|
||
contracts.
|
||
|
||
The implementer is encouraged to use simple, descriptive names in the
|
||
source code to describe the applicable seal states.
|
||
|
||
Use cases of sealing include:
|
||
|
||
- Whether more tokens can be minted
|
||
|
||
- Allow ownership of a contract to be transferred
|
||
|
||
- The expiry time of a token (see `Expire`)
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
0d7491f8
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface ISeal {
|
||
// Seal state has changed.
|
||
event SealStateChange(bool indexed _final, uint256 _sealState);
|
||
|
||
// The current seal state.
|
||
function sealState() external view returns(uint256);
|
||
|
||
// The numeric seal state in everything sealable has been sealed.
|
||
function maxSealState() external view returns(uint256);
|
||
}
|
||
|
||
#### Example implementation
|
||
|
||
<https://git.grassecon.net/cicnet/erc20-demurrage-token.git>
|
||
|
||
### TokenLimit
|
||
|
||
Define limits of value amounts of tokens that individual addresses can
|
||
hold.
|
||
|
||
Limits are inclusive; a limit for 42 means transfer resulting in a token
|
||
balance *higher* than 42 should be rejected.
|
||
|
||
A return value of 0 indicates that the token is categorically not
|
||
accepted by the holder.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
23778613
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface ITokenLimit {
|
||
// Returns limit of total value a holder will accept of a specific token.
|
||
// The value limit returned is inclusive; A limit of 42 means any operation resulting in a balance OVER 42 should be rejected.
|
||
// A value of 0 means that no value of the token is accepted.
|
||
function limitOf(address _token, address _holder) external view returns(uint256);
|
||
}
|
||
|
||
#### Reference implementations
|
||
|
||
- <git://holbrook.no/erc20-limiter.git>
|
||
|
||
### TokenQuote
|
||
|
||
Quote an output token value for a given value of input tokens.
|
||
|
||
Both input and output value is denominated in the smallest available
|
||
unit of respective tokens.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
dbb21d40
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface ITokenQuote {
|
||
// Returns, within a current context, what value of outTokens the given value of inTokens translates to.
|
||
// The values are given in smallest unit of each respective token.
|
||
function valueFor(address _outToken, address _inToken, uint256 value) external view returns (uint256);
|
||
}
|
||
|
||
#### Example implementation
|
||
|
||
- <git://holbrook.no/erc20-limiter.git>
|
||
|
||
### TokenRateChange
|
||
|
||
Enables detection of properties for CIC tokens that change value over
|
||
time, e.g. through demurrage.
|
||
|
||
It allows defining the granularity of the rate of change, aswell as a
|
||
frequency for which the rate of change is applied.
|
||
|
||
A method for canonical value change calculations is also provided.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
b716af03
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface ITokenChangeRate {
|
||
// Time unit resolution for rate of change.
|
||
// A value of 0 indicates no rate of change,
|
||
function changeTimeUnit() external view returns(uint256);
|
||
|
||
// Rate of change per changeTimeUnit(), signed integer.
|
||
// An effective value of 0 indicates no rate of change.
|
||
function changeRate() external view returns (int256);
|
||
|
||
// Number of decimals with which the changeRate is defined.
|
||
// changeRate() should be divided by 10 ** changeRateDecimals() to obtain effective value
|
||
function changeRateDecimals() external view returns(uint8);
|
||
|
||
// Timestamp from when rate of change should be applied.
|
||
// A value of 0 indicates no rate of change,
|
||
function changeStartTime() external view returns(uint256);
|
||
|
||
// Calculate value with change rate applied for given amount of time units.
|
||
// Will calculate compounded change over the given amount of time units
|
||
function applyChange(int256 _value, uint256 _changeTimeUnits) external view returns(int256);
|
||
}
|
||
|
||
#### Reference implementations
|
||
|
||
- <git://holbrook.no/erc20-demurrage-token.git>
|
||
|
||
### TokenSwap
|
||
|
||
Token swap interface that can fit token escrow purposes aswell as token
|
||
swap contracts.
|
||
|
||
Optionally may define a `defaultToken`, that may among other things be
|
||
used for `withdraw()` calls without an `inToken`.
|
||
|
||
An explicit *ERC20 approval* of the balance to be transacted will
|
||
usually be required for the implementing contract.
|
||
|
||
If the value 0 is passed as argument to `deposit` or `withdraw`,
|
||
implementers can choose one of two possible outcomes:
|
||
|
||
- Noop. 0 *must* be returned.
|
||
|
||
- Use *balance* or the max available *allowance*. The actual (spent)
|
||
value *must* be returned.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
4146b765
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface ITokenSwap {
|
||
// Emitted when a new deposit has been made.
|
||
event Deposit(address indexed _token, uint256 _value);
|
||
|
||
// Default token used to access the token swap.
|
||
// Returns zero-address if no default token is defined.
|
||
function defaultToken() external returns (address);
|
||
|
||
// Add inToken liquidity to the tune of given value.
|
||
// Requires token approval for the corresponding value.
|
||
// If value is 0, up to the full approval MAY be used for the transfer.
|
||
function deposit(address _inToken, uint256 _value) external returns (uint256);
|
||
|
||
// Withdraw pending outToken balance of given value in the pool for the sender.
|
||
// May require token approval for defaultToken if used by contract as exchange for the withdrawal.
|
||
// If value is 0, up to the full approval value MAY be used for the transfer.
|
||
function withdraw(address _outToken, uint256 _value) external returns (uint256);
|
||
|
||
// Exchange inToken equalling given value for outToken.
|
||
// Requires token approval for the value of inToken.
|
||
// If value is 0, up to the full approval value MAY be used for the transfer.
|
||
function withdraw(address _outToken, address _inToken, uint256 _value) external returns (uint256);
|
||
}
|
||
|
||
#### Reference implementations
|
||
|
||
- <git://holbrook.no/erc20-pool.git>
|
||
|
||
#### Handling deposits
|
||
|
||
The implementation is free to decide whether deposits can be recovered
|
||
directly, or if they will be locked in the smart contract - temporarily
|
||
or permanently.
|
||
|
||
For the duration deposits are locked, they are part of the smart
|
||
contract’s swap liquidity. During this time, locked deposits may only be
|
||
withdrawn in exchange for other tokens accepted by the contract.
|
||
|
||
Deposits that are not locked should be withdrawable using the
|
||
`withdraw(address,uint256)` (`0xf3fef3a3`) method signature.
|
||
|
||
Of course, as with most swap contracts, the tokens available for
|
||
withdrawal by the holder may not necessarily match the tokens that were
|
||
deposited by the holder.
|
||
|
||
### TokenVote
|
||
|
||
Execute elections with granular ERC20 token votes.
|
||
|
||
A proposal submitted for vote may or may not contain multiple options.
|
||
If multiple options are available, an ERC20 token holder may distribute
|
||
its vote among the options with the granularity of the token balance.
|
||
|
||
Voted tokens **SHOULD** be locked until the voting has finalized.
|
||
|
||
Finalization of voting should be callable by anyone.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
f2e0bfeb
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface ITokenVote {
|
||
|
||
// A new proposal has been created.
|
||
event ProposalAdded(uint256 indexed _blockDeadline, uint256 indexed voteTargetPpm, uint256 indexed _proposalIdx);
|
||
|
||
// A proposal vote has been completed.
|
||
// The proposal is identified by the serial number in _proposalIdx. It is up to the implementer to define how the proposal should be retrieved by index.
|
||
// The proposal result may be in one of three states:
|
||
// * Ratified (_cancelled == false, _insufficient == false)
|
||
// * Cancelled (_cancelled == true, _insufficient == false)
|
||
// * Not reached quorum (_cancelled == false, _insufficient == true)
|
||
event ProposalCompleted(uint256 indexed _proposalIdx, bool indexed _cancelled, bool indexed _insufficient, uint256 _totalVote);
|
||
|
||
// Propose a new vote.
|
||
// Voting is active until one of:
|
||
// * total cancel vote reach quorum (_targetVotePpm, ppm = parts-per-million).
|
||
// * _blockWait blocks from now.
|
||
function propose(bytes32 _description, uint256 _blockWait, uint24 _targetVotePpm) external returns (uint256);
|
||
|
||
// Add a voting option to a proposal
|
||
function addOption(uint256 _proposalIdx, bytes32 _description) external;
|
||
|
||
// Get number of options available for the proposal.
|
||
// This decides the boundary of the index that can be used with voteOptions(...)
|
||
// If the result is 0, vote(...) can be used aswell.
|
||
function optionCount(uint256 _proposalIdx) external view returns(uint256);
|
||
|
||
// Get proposal option. Assumes that proposal was created with proposeMulti(...)
|
||
function getOption(uint256 _proposalIdx, uint256 _optionIdx) external view returns (bytes32);
|
||
|
||
// Get vote count for the given option.
|
||
// If proposal has no options, it should be called with _optionIdx = 0
|
||
function voteCount(uint256 _proposalIdx, uint256 _optionIdx) external view returns(uint256);
|
||
|
||
// Vote on a proposal without options.
|
||
// Assumes that proposal was created with propose(...) and will fail otherwise.
|
||
function vote(uint256 _value) external returns (bool);
|
||
|
||
// Vote on a proposal option. Assumes that proposal was created with proposeMulti(...).
|
||
// Must work with a non-option proposal if _optionIndex is 0.
|
||
function voteOption(uint256 _optionIndex, uint256 _value) external returns (bool);
|
||
|
||
// Vote to cancel a proposal.
|
||
// If cancel has the majority:
|
||
// * A vote without options will have rejected the proposal description.
|
||
// * A vote with options will have rejected the proposal description as well as all option descriptions.
|
||
function voteCancel(uint256 _value) external returns (bool);
|
||
|
||
// Finalize the vote for a proposal.
|
||
// May be called if deadline has been passed, or if:
|
||
// * quorum has been reached with cancel votes.
|
||
// * quorum has been reached and proposal has no/only one option.
|
||
function finalize() external returns (bool);
|
||
}
|
||
|
||
#### Reference implementations
|
||
|
||
- <git://holbrook.no/evm-tokenvote.git>
|
||
|
||
### Writer
|
||
|
||
A complement to ERC173, which allows definition of a class of
|
||
super-users for a contract.
|
||
|
||
A super-user address may perform *more* actions than a "normal" address,
|
||
aswell as *some* actions normally limited to the *contract owner*.
|
||
|
||
If an *contract owner* is defined, No super-user should be able to
|
||
perform actions that *contract owner* cannot perform.
|
||
|
||
Typically, only the *contract owner*, if it is defined, can add or
|
||
remove a super-user.
|
||
|
||
Some use-case examples of super-user actions include:
|
||
|
||
- Mint new tokens.
|
||
|
||
- Change the amount dispensed by the faucet.
|
||
|
||
- Edit access control lists.
|
||
|
||
#### ERC165 Interface identifier
|
||
|
||
abe1f1f5
|
||
|
||
#### Solidity interface definition
|
||
|
||
interface IWriter {
|
||
// A writer has been added by _executor
|
||
event WriterAdded(address _writer);
|
||
|
||
// A writer has been removed by _executor
|
||
event WriterDeleted(address _writer);
|
||
|
||
// Add a new writer to the contract.
|
||
function addWriter(address _writer) external returns (bool);
|
||
|
||
// Remove existing writer from the contract.
|
||
function deleteWriter(address _writer) external returns (bool);
|
||
|
||
// Check whether the given address is a writer.
|
||
function isWriter(address _writer) external view returns (bool);
|
||
}
|
||
|
||
#### Example implementation
|
||
|
||
<https://git.grassecon.net/cicnet/erc20-demurrage-token.git>
|