@athenalend/athena-token
v0.0.2
Published
Athena ERC20 token
Downloads
8
Readme
Athena Token design
ATHENA is an ERC-20 compatible token. It implements governance-inspired features, and will allow Athena to bootstrap the rewards program for safety and ecosystem growth. The following document explains the main features of ATHENA, it’s monetary policy, and the redemption process from LEND.
Roles
The initial ATHENA token implementation does not have any admin roles configured. The contract will be proxied using the Openzeppelin implementation of the EIP-1967 Transparent Proxy pattern. The proxy has an Admin role, and the Admin of the proxy contract will be set upon deployment to the Athena governance contracts.
ERC-20
The ATHENA token implements the standard methods of the ERC-20 interface. A balance snapshot feature has been added to keep track of the balances of the users at specific block heights. This will help with the Athena governance integration of ATHENA.
ATHENA also integrates the EIP 2612 permit
function, that will allow gasless transaction and one tx approval/transfer.
LendToAthenaMigrator
Smart contract for LEND token holders to execute the migration to the ATHENA token, using part of the initial emission of ATHENA for it.
The contract is covered by a proxy, whose owner will be the ATHENA governance. Once the governance passes the corresponding proposal, the proxy will be connected to the implementation and LEND holders will be able to call the migrateFromLend()
function, which, after LEND approval, will pull LEND from the holder wallet and transfer back an equivalent ATHENA amount defined by the LEND_ATHENA_RATIO
constant.
One tradeOff of migrateFromLend()
is that, as the ATHENA total supply will be lower than LEND, the LEND_ATHENA_RATIO
will be always > 1, causing a loss of precision for amounts of LEND that are not multiple of LEND_ATHENA_RATIO
. E.g. a person sending 1.000000000000000022 LEND, with a LEND_ATHENA_RATIO
== 100, will receive 0.01 ATHENA, losing the value of the last 22 small units of LEND.
Taking into account the current value of LEND and the future value of ATHENA, a lack of precision for less than LEND_ATHENA_RATIO small units represents a value several orders of magnitude smaller than 0.01$. We evaluated some potential solutions for this, specifically:
- Rounding half up the amount of ATHENA returned from the migration. This opens up to potential attacks where users might purposely migrate less than LEND_ATHENA_RATIO to obtain more ATHENA as a result of the round up.
- Returning back the excess LEND: this would leave LEND in circulation forever, which is not the expected end result of the migration.
- Require the users to migrate only amounts that are multiple of LEND_ATHENA_RATIO: This presents considerable UX friction.
None of those present a better outcome than the implemented solution.
The Redemption process
The first step to bootstrap the ATHENA emission is to deploy the ATHENA token contract and the LendToAthenaMigrator contract. This task will be performed by the Athena team. Upon deployment, the ownership of the Proxy of the ATHENA contract and the LendToAthenaMigrator will be set to the Athena Governance. To start the LEND redemption process at that point, the Athena team will create an AIP (Athena Improvement Proposal) and submit a proposal to the Athena governance. The proposal will, once approved, activate the LEND/ATHENA redemption process and the ecosystem incentives, which will mark the initial emission of ATHENA on the market. The result of the migration procedure will see the supply of LEND being progressively locked within the new ATHENA smart contract, while at the same time an equivalent amount of ATHENA is being issued. The amount of ATHENA equivalent to the LEND tokens burned in the initial phase of the ATHENA protocol will remain locked in the LendToAthenaMigrator contract.
Technical implementation
Changes to the Openzeppelin original contracts
In the context of this implementation, we needed apply the following changes to the OpenZepplin implementation:
- In
/contracts/open-zeppelin/ERC20.sol
, line 44 and 45,_name
and_symbol
have been changed fromprivate
tointernal
- We extended the original
Initializable
class from the Openzeppelin contracts and created aVersionedInitializable
contract. The main differences compared to theInitializable
are:
- The boolean
initialized
has been replaced with auint256 latestInitializedRevision
. - The
initializer()
modifier fetch the revision of the implementation using agetRevision()
function defined in the implementation contract. Theinitializer
modifier forces that an implementation - with a bigger revision number than the current one is being initialized
The change allows us to call initialize()
on multiple implementations, that was not possible with the original Initializable
implementation from OZ.
_beforeTokenTransfer hook
We override the _beforeTokenTransfer function on the OZ base ERC20 implementation in order to include the following features:
- Snapshotting of balances every time an action involved a transfer happens (mint, burn, transfer or transferFrom). If the account does a transfer to itself, no new snapshot is done.
- Call to the Athena governance contract forwarding the same input parameters of the
_beforeTokenTransfer
hook. Its an assumption that the Athena governance contract is a trustable party, being its responsibility to control all potential reentrancies if calling back the AthenaToken. If the account does a transfer to itself, no interaction with the Athena governance contract should happen.
Development deployment
For development purposes, you can deploy AthenaToken and LendToAthenaMigrator to a local network via the following command:
npm run dev:deployment
For any other network, you can run the deployment in the following way
npm run ropsten:deployment
You can also set an optional $ATHENA_ADMIN
enviroment variable to set an ETH address as the admin of the AthenaToken and LendToAthenaMigrator proxies. If not set, the deployment will set the second account of the accounts
network configuration at buidler.config.ts
.
Mainnet deployment
You can deploy AthenaToken and LendToAthenaMigrator to the mainnet network via the following command:
ATHENA_ADMIN=governance_or_ETH_address
LEND_TOKEN=lend_token_address
npm run main:deployment
The $ATHENA_ADMIN
enviroment variable is required to run, set an ETH address as the admin of the AthenaToken and LendToAthenaMigrator proxies. Check buidler.config.ts
for more required enviroment variables for Mainnet deployment.
The proxies will be initialized during the deployment with the $ATHENA_ADMIN
address, but the smart contracts implementations will not be initialized.
Enviroment Variables
| Variable | Description | | ----------------------- | ----------------------------------------------------------------------------------- | | $ATHENA_ADMIN | ETH Address of the admin of Proxy contracts. Optional for development. | | $LEND_TOKEN | ETH Address of the LEND token. Optional for development. | | $INFURA_KEY | Infura key, only required when using a network different than local network. | | $MNEMONIC_<NETWORK> | Mnemonic phrase, only required when using a network different than local network. | | $ETHERESCAN_KEY | Etherscan key, not currently used, but will be required for contracts verification. |
Audits v1
The Solidity code in this repository has undergone 2 traditional smart contracts' audits by Consensys Diligence and Certik, and properties' verification process by Certora. The reports are:
Audits v2
The new StakedAthenaV2 implementation has been audited by Peckshield and property checked by Certora.
Credits
For the proxy-related contracts, we have used the implementation of our friend from OpenZeppelin.
License
The contents of this repository are under the AGPLv3 license.