Address Details
contract
token
0xe481988Ef9065CcD024568BBf962f378A7Fa80B8
- Creator
- 0x15933c–ed3d58 at 0xd82950–8ba2cd
- Balance
- 0 CELO ( )
- Locked CELO Balance
- 0.00 CELO
- Voting CELO Balance
- 0.00 CELO
- Pending Unlocked Gold
- 0.00 CELO
- Tokens
-
Fetching tokens...
- Transactions
- 7 Transactions
- Transfers
- 23 Transfers
- Gas Used
- 184,984
- Last Balance Update
- 13304071
Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
Minimal Proxy Contract for 0x18f7fd11ee989b8b708cddfedbd1b75887d83523.
EIP-1167 - minimal bytecode implementation that delegates all calls to a known address
EIP-1167 - minimal bytecode implementation that delegates all calls to a known address
- Contract name:
- CarbonCreditBundleToken
- Optimization enabled
- true
- Compiler version
- v0.8.13+commit.abaa5c0e
- Optimization runs
- 200
- Verified at
- 2022-05-19T08:42:54.100249Z
project:/contracts/CarbonCreditBundleToken.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.13; import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol"; import "./abstracts/AbstractToken.sol"; import './CarbonCreditToken.sol'; /// @author FlowCarbon LLC /// @title A Carbon Credit Bundle Token Reference Implementation contract CarbonCreditBundleToken is AbstractToken { using SafeERC20Upgradeable for CarbonCreditToken; using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet; struct TokenChecksums { address _tokenAddress; uint256 _amount; } /// @notice Emitted when someone bundles tokens into the bundle token /// @param account - the token sender /// @param amount - the amount of tokens to bundle /// @param tokenAddress - the address of the vanilla underlying event Bundle(address account, uint256 amount, address tokenAddress); /// @notice Emitted when someone unbundles tokens from the bundle /// @param account - the token recipient /// @param amount - the amount of tokens to bundle /// @param tokenAddress - the address of the vanilla underlying event Unbundle(address account, uint256 amount, address tokenAddress); /// @notice Emitted when a new token is added to the bundle /// @param tokenAddress - the new token that is added event TokenAdded(address tokenAddress); /// @notice Emitted when a new token is removed from the bundle /// @param tokenAddress - the token that has been removed event TokenRemoved(address tokenAddress); /// @notice Emitted when the minimum vintage requirements change /// @param vintage - the new vintage after the update event VintageIncremented(uint16 vintage); /// @notice The fee divisor taken upon unbundling /// @dev 1/feeDivisor is the fee in % uint256 public feeDivisor; /// @notice The minimal vintage uint16 public vintage; /// @notice The CarbonCreditTokens that form this bundle EnumerableSetUpgradeable.AddressSet private _tokenAddresses; /// @notice Keeps track of checksums, amounts and underlying tokens mapping (bytes32 => TokenChecksums) private _offsetChecksums; function initialize( string memory name_, string memory symbol_, uint16 vintage_, CarbonCreditToken[] memory tokens_, address owner_, uint256 feeDivisor_ ) external initializer { require(vintage_ > 2000, 'vintage out of bounds'); require(vintage_ < 2100, 'vintage out of bounds'); __AbstractToken_init(name_, symbol_, owner_); vintage = vintage_; feeDivisor = feeDivisor_; for (uint256 i = 0; i < tokens_.length; i++) { _addToken(tokens_[i]); } } /// @notice increasing the vintage /// @dev existing tokens can no longer be bundled, new tokens require the new vintage /// @param years_ - number of years to increment the vintage, needs to be smaller than 10 function incrementVintage(uint16 years_) external onlyOwner returns (uint16) { require(years_ <= 10, "vintage increment out of bounds"); vintage += years_; emit VintageIncremented(vintage); return vintage; } /// @notice Checks if a token exists /// @param token_ - a carbon credit token function hasToken(CarbonCreditToken token_) public view returns (bool) { return _tokenAddresses.contains(address(token_)); } /// @notice Number of tokens in this bundle function tokenCount() external view returns (uint256) { return _tokenAddresses.length(); } /// @notice A token from the bundle /// @param index_ - the index position taken from tokenCount() function tokenAtIndex(uint256 index_) external view returns (address) { return _tokenAddresses.at(index_); } /// @notice Adds a new token to the bundle. The token has to match the TokenDetails signature of the bundle /// @param token_ - a carbon credit token that is added to the bundle. function addToken(CarbonCreditToken token_) external onlyOwner returns (bool) { _addToken(token_); return true; } /// @dev Private function to execute addToken so it can be used in the initalizer function _addToken(CarbonCreditToken token_) private returns (bool) { require(!hasToken(token_), "token already exists"); require(token_.vintage() >= vintage, "vintage mismatch"); require(address(token_) != address(this), "cannot add to self"); _tokenAddresses.add(address(token_)); emit TokenAdded(address(token_)); return true; } /// @notice Removes a token from the bundle /// @param token_ - the carbon credit token to remove function removeToken(CarbonCreditToken token_) external onlyOwner returns (bool) { address tokenAddress = address(token_); require(_tokenAddresses.contains(tokenAddress), "token does not exists"); require(token_.balanceOf(address(this)) == 0, "token has remaining balance"); _tokenAddresses.remove(tokenAddress); emit TokenRemoved(tokenAddress); return true; } /// @notice Bundles an underlying into the bundle, bundle need to be approved beforehand /// @param token_ - the carbon credit token to bundle /// @param amount_ - the amount one wants to bundle function bundle(CarbonCreditToken token_, uint256 amount_) external returns (bool) { address tokenAddress = address(token_); require(_tokenAddresses.contains(tokenAddress), "token does not exists"); require(token_.vintage() >= vintage, "token outdated"); _mint(_msgSender(), amount_); token_.safeTransferFrom(_msgSender(), address(this), amount_); emit Bundle(_msgSender(), amount_, tokenAddress); return true; } /// @notice Unbundles an underlying from the bundle, note that a fee may apply /// @param token_ - the carbon credit token to undbundle /// @param amount_ - the amount one wants to unbundle (including fee) /// @return the amount of tokens after fees function unbundle(CarbonCreditToken token_, uint256 amount_) external returns (uint256) { address tokenAddress = address(token_); require(_tokenAddresses.contains(tokenAddress), "token does not exists"); require(token_.balanceOf(address(this)) >= amount_, "amount exceeds the token balance"); _burn(_msgSender(), amount_); uint256 amountToUnbundle = amount_; if (feeDivisor > 0) { uint256 feeAmount = amount_ / feeDivisor; amountToUnbundle = amount_ - feeAmount; token_.safeTransfer(owner(), feeAmount); } token_.safeTransfer(_msgSender(), amountToUnbundle); emit Unbundle(_msgSender(), amountToUnbundle, tokenAddress); return amountToUnbundle; } /// @notice The contract owner can finalize the offsetting process once the underlying tokens have been offset /// @param token_ - the carbon credit token to finalize the offsetting process for /// @param amount_ - the number of token to finalize offsetting process for /// @param checksum_ - the checksum associated with the underlying offset event function finalizeOffset(CarbonCreditToken token_, uint256 amount_, bytes32 checksum_) external onlyOwner returns (bool) { address tokenAddress = address(token_); require(_tokenAddresses.contains(tokenAddress), "token does not exists"); require(_offsetChecksums[checksum_]._amount == 0, "checksum was already used"); require(amount_ <= pendingBalance, 'offset exceeds pending balance'); require(token_.balanceOf(address(this)) >= amount_, "amount exceeds the token balance"); pendingBalance -= amount_; _offsetChecksums[checksum_] = TokenChecksums(tokenAddress, amount_); offsetBalance += amount_; token_.burn(amount_); emit FinalizeOffset(amount_, checksum_); return true; } /// @dev See ICarbonCreditTokenInterface function amountOffsettedWithChecksum(bytes32 checksum_) external view returns (uint256) { return _offsetChecksums[checksum_]._amount; } /// @param checksum_ - the checksum of the associated offset event of the underlying /// @return the address of the CarbonCreditToken that has been offset with this checksum function tokenAddressOffsettedWithChecksum(bytes32 checksum_) external view returns (address) { return _offsetChecksums[checksum_]._tokenAddress; } }
Contract ABI
[{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Bundle","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"address","name":"tokenAddress","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"FinalizeOffset","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"bytes32","name":"checksum","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"Offset","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"TokenAdded","inputs":[{"type":"address","name":"tokenAddress","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"TokenRemoved","inputs":[{"type":"address","name":"tokenAddress","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Unbundle","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"address","name":"tokenAddress","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"VintageIncremented","inputs":[{"type":"uint16","name":"vintage","internalType":"uint16","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"addToken","inputs":[{"type":"address","name":"token_","internalType":"contract CarbonCreditToken"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"amountOffsettedWithChecksum","inputs":[{"type":"bytes32","name":"checksum_","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"bundle","inputs":[{"type":"address","name":"token_","internalType":"contract CarbonCreditToken"},{"type":"uint256","name":"amount_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"decreaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"subtractedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"feeDivisor","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"finalizeOffset","inputs":[{"type":"address","name":"token_","internalType":"contract CarbonCreditToken"},{"type":"uint256","name":"amount_","internalType":"uint256"},{"type":"bytes32","name":"checksum_","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasToken","inputs":[{"type":"address","name":"token_","internalType":"contract CarbonCreditToken"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"increaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"addedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"incrementVintage","inputs":[{"type":"uint16","name":"years_","internalType":"uint16"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"string","name":"name_","internalType":"string"},{"type":"string","name":"symbol_","internalType":"string"},{"type":"uint16","name":"vintage_","internalType":"uint16"},{"type":"address[]","name":"tokens_","internalType":"contract CarbonCreditToken[]"},{"type":"address","name":"owner_","internalType":"address"},{"type":"uint256","name":"feeDivisor_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"offset","inputs":[{"type":"uint256","name":"amount_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"offsetAmountAtIndex","inputs":[{"type":"address","name":"address_","internalType":"address"},{"type":"uint256","name":"index_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"offsetBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"offsetBalanceOf","inputs":[{"type":"address","name":"account_","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"offsetCountOf","inputs":[{"type":"address","name":"address_","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"offsetOnBehalfOf","inputs":[{"type":"address","name":"account_","internalType":"address"},{"type":"uint256","name":"amount_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"offsetTimeAtIndex","inputs":[{"type":"address","name":"address_","internalType":"address"},{"type":"uint256","name":"index_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pendingBalance","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"removeToken","inputs":[{"type":"address","name":"token_","internalType":"contract CarbonCreditToken"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"tokenAddressOffsettedWithChecksum","inputs":[{"type":"bytes32","name":"checksum_","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"tokenAtIndex","inputs":[{"type":"uint256","name":"index_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokenCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"sender","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"unbundle","inputs":[{"type":"address","name":"token_","internalType":"contract CarbonCreditToken"},{"type":"uint256","name":"amount_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint16","name":"","internalType":"uint16"}],"name":"vintage","inputs":[]}]
Contract Creation Code
0x3d602d80600a3d3981f3363d3d373d3d3d363d7318f7fd11ee989b8b708cddfedbd1b75887d835235af43d82803e903d91602b57fd5bf3
Deployed ByteCode
0x363d3d373d3d3d363d7318f7fd11ee989b8b708cddfedbd1b75887d835235af43d82803e903d91602b57fd5bf3