A secure smart contract that enables users to retire EDEN tokens for ETH at a fixed exchange rate during a specified time window. The contract implements an atomic swap mechanism where users receive ETH immediately upon depositing EDEN tokens.
- Fixed Exchange Rate: Admin-defined exchange rate set at deployment
- Atomic Swaps: Users receive ETH immediately when depositing EDEN
- Time-Bounded Window: Configurable deposit period using block numbers
- Permanent Token Lock: EDEN tokens are permanently locked (effectively burned)
- Admin Controls: Pausable functionality and ETH recovery after deposit window
- Security: ReentrancyGuard protection and comprehensive input validation
The system consists of:
EdenTokenRetirement: Core contract managing the EDEN-to-ETH exchanges- Fixed exchange rate immutably set at deployment
- Immediate ETH distribution upon EDEN deposit
- Deposit EDEN tokens and receive ETH instantly at fixed rate
- Gas-efficient permit-based deposits using EIP-2612 (single transaction)
- Admin can deposit ETH to fund exchanges
- Admin can withdraw remaining ETH after deposit window closes
- Pausable functionality for emergency situations
- View functions to check exchange rates and balances
- Node.js (v14 or higher)
- npm or yarn
- Hardhat
- Clone the repository:
git clone https://github.com/eden-network/token-retirement.git
cd token-retirement- Install dependencies:
npm installRun the test suite:
npm testFor gas reporting:
npm run test:gasGenerate test coverage report:
npm run test:coverageThe contract deployment uses environment variables configured in the .env file.
- Set up your
.envfile with the following variables:
# EDEN token address (required)
EDEN_ADDRESS=0x1559fa1b8f28238fd5d76d9f434ad86fd20d1559
# Exchange rate: EDEN tokens per 1 ETH (default: 57000)
EXCHANGE_RATE=57000
# Start date for deposits (format: YYYY-MM-DD)
START_DATE=2025-07-29
# Optional start time (format: HH:MM or HH:MM:SS, UTC)
# START_TIME=12:00
# End date for EDEN deposits (format: YYYY-MM-DD)
END_DATE=2025-07-31
# Optional end time (format: HH:MM or HH:MM:SS, UTC)
# END_TIME=23:59
# OR use duration in blocks instead of end date (mutually exclusive with END_DATE)
# EDEN_DEPOSIT_DURATION=86400 # ~14 days at 12s/block
# Contract owner address (defaults to deployer if not set)
CONTRACT_OWNER=0xYourOwnerAddress
# Verify contract on Etherscan after deployment
VERIFY=true
# For mainnet deployments, set this to true to confirm
# CONFIRM=true
# Optional gas configuration
# GAS_PRICE=20 # in gwei
# GAS_LIMIT=8000000EDEN_ADDRESS: Address of the EDEN token contract (required)EXCHANGE_RATE: Number of EDEN tokens per 1 ETH (defaults to 57000 for 1000 EDEN = 0.0175429 ETH)CONTRACT_OWNER: Owner address for the contract (defaults to deployer)VERIFY: Set totrueto verify contract on Etherscan after deploymentCONFIRM: Set totrueto confirm mainnet deployment
-
Duration in blocks:
- Use
EDEN_DEPOSIT_DURATION=86400for ~14 days at 12s/block
- Use
-
Date-based (recommended):
- Use
START_DATEandEND_DATEin YYYY-MM-DD format - Optionally add
START_TIMEandEND_TIMEfor specific times (UTC) - If no time is specified, start defaults to 00:00:00 and end defaults to 23:59:59
- Use
Local deployment:
npm run deploy:localTestnet deployment:
npm run deploy:sepoliaMainnet deployment:
npm run deploy:mainnetBasic Sepolia deployment (in .env):
EDEN_ADDRESS=0x1559fa1b8f28238fd5d76d9f434ad86fd20d1559
EXCHANGE_RATE=57000
START_DATE=2025-07-29
END_DATE=2025-08-29
CONTRACT_OWNER=0xYourOwnerAddress
VERIFY=trueDuration-based deployment (in .env):
EDEN_ADDRESS=0x1559fa1b8f28238fd5d76d9f434ad86fd20d1559
EXCHANGE_RATE=57000
EDEN_DEPOSIT_DURATION=172800 # ~30 days
CONTRACT_OWNER=0xYourOwnerAddress
VERIFY=truePrecise timing deployment (in .env):
EDEN_ADDRESS=0x1559fa1b8f28238fd5d76d9f434ad86fd20d1559
EXCHANGE_RATE=1000
START_DATE=2024-12-25
START_TIME=12:00:00
END_DATE=2024-12-31
END_TIME=23:59:59
CONTRACT_OWNER=0xYourOwnerAddress
VERIFY=trueMainnet deployment (in .env):
EDEN_ADDRESS=0x1559fa1b8f28238fd5d76d9f434ad86fd20d1559
EXCHANGE_RATE=57000
START_DATE=2024-12-25
END_DATE=2024-12-31
CONTRACT_OWNER=0xYourOwnerAddress
VERIFY=true
CONFIRM=true # Required for mainnet-
Fund the contract with ETH:
- Send ETH to the deployed contract address before the deposit window starts
- Ensure sufficient ETH for expected EDEN deposits
-
Verify the contract (if on public network):
npx hardhat verify --network <network> <contract-address> <constructor-args>
-
Monitor deposits:
- Check
totalEdenDeposited()to track EDEN deposits - Use
getContractETHBalance()to monitor available ETH
- Check
-
Check exchange rate:
uint256 rate = contract.EXCHANGE_RATE(); // EDEN per 1 ETH
-
Calculate ETH received:
uint256 ethAmount = contract.getETHAmount(edenAmount);
-
Exchange EDEN for ETH (two options):
Option A: Traditional (2 transactions):
- First approve the contract to spend EDEN tokens
- Call
depositEdenForETH(amount)during the deposit window - Receive ETH immediately
Option B: With Permit (1 transaction, gas efficient):
- Sign permit message off-chain
- Call
depositEdenForETHWithPermit(amount, deadline, v, r, s) - Approve and swap in single transaction
-
Fund contract: Send ETH directly to contract address
-
Pause/Unpause (emergency):
contract.pause(); contract.unpause();
-
Withdraw remaining ETH (after deposit window):
contract.withdrawRemainingETH();
- EDEN tokens sent to the contract are permanently locked
- Contract uses ReentrancyGuard for withdrawal protection
- Exchange rate is immutable after deployment
- Admin cannot withdraw EDEN tokens
- Permit functionality uses EIP-2612 standard for secure off-chain approvals
- Comprehensive test coverage for edge cases and permit scenarios
Compile contracts:
npm run compileRun linter:
npm run lintFix linting issues:
npm run lint:fixFormat code:
npm run formatStart local node:
npm run nodeThis project is licensed under the MIT License