Skip to content

Commit

Permalink
chore: change to aERC20
Browse files Browse the repository at this point in the history
  • Loading branch information
0xTimepunk committed Nov 24, 2023
1 parent 593db90 commit 3345669
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 207 deletions.
2 changes: 1 addition & 1 deletion lib/openzeppelin-contracts
2 changes: 1 addition & 1 deletion lib/solmate
62 changes: 31 additions & 31 deletions src/ERC1155A.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { IERC1155A } from "./interfaces/IERC1155A.sol";
import { Strings } from "openzeppelin-contracts/contracts/utils/Strings.sol";
import { IERC1155Errors } from "openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol";
import { IERC1155Receiver } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol";
import { IsERC20 } from "./interfaces/IsERC20.sol";
import { IaERC20 } from "./interfaces/IaERC20.sol";

/**
* @title ERC1155A
Expand All @@ -16,7 +16,7 @@ import { IsERC20 } from "./interfaces/IsERC20.sol";
* 2. Allowance management for single id approve
* 3. Metadata build out of baseURI and id uint value into offchain metadata address
* 4. Range based approvals
* 5. Converting to synthetic ERC20s back and forth
* 5. Converting to ERC20s back and forth (called AERC20)
*
*/
abstract contract ERC1155A is IERC1155A, IERC1155Errors {
Expand All @@ -35,8 +35,8 @@ abstract contract ERC1155A is IERC1155A, IERC1155Errors {
/// @dev Implementation copied from solmate/ERC1155
mapping(address => mapping(address => bool)) public isApprovedForAll;

/// @dev mapping of token ids to synthetic token addresses
mapping(uint256 id => address syntheticToken) public synthethicTokenId;
/// @dev mapping of token ids to aErc20 token addresses
mapping(uint256 id => address aErc20Token) public aErc20TokenId;

///////////////////////////////////////////////////////////////////////////
/// ERC1155-A LOGIC SECTION ///
Expand Down Expand Up @@ -252,18 +252,18 @@ abstract contract ERC1155A is IERC1155A, IERC1155Errors {
}

/*///////////////////////////////////////////////////////////////
SERC20 AND TRANSMUTE LOGIC
AERC20 AND TRANSMUTE LOGIC
//////////////////////////////////////////////////////////////*/

/// @inheritdoc IERC1155A
function registerSERC20(uint256 id) external payable virtual override returns (address) {
function registerAERC20(uint256 id) external payable virtual override returns (address) {
if (_totalSupply[id] == 0) revert ID_NOT_MINTED_YET();
if (synthethicTokenId[id] != address(0)) revert SYNTHETIC_ERC20_ALREADY_REGISTERED();
if (aErc20TokenId[id] != address(0)) revert AERC20_ALREADY_REGISTERED();

address syntheticToken = _registerSERC20(id);
address aErc20Token = _registerAERC20(id);

synthethicTokenId[id] = syntheticToken;
return synthethicTokenId[id];
aErc20TokenId[id] = aErc20Token;
return aErc20TokenId[id];
}

/// @inheritdoc IERC1155A
Expand All @@ -272,10 +272,10 @@ abstract contract ERC1155A is IERC1155A, IERC1155Errors {
_batchBurn(owner, msg.sender, ids, amounts);

for (uint256 i = 0; i < ids.length; ++i) {
address sERC20Token = synthethicTokenId[ids[i]];
if (sERC20Token == address(0)) revert SYNTHETIC_ERC20_NOT_REGISTERED();
address aERC20Token = aErc20TokenId[ids[i]];
if (aERC20Token == address(0)) revert AERC20_NOT_REGISTERED();

IsERC20(sERC20Token).mint(owner, amounts[i]);
IaERC20(aERC20Token).mint(owner, amounts[i]);
}

emit TransmutedBatchToERC20(owner, ids, amounts);
Expand All @@ -291,10 +291,10 @@ abstract contract ERC1155A is IERC1155A, IERC1155Errors {
override
{
for (uint256 i = 0; i < ids.length; ++i) {
address sERC20Token = synthethicTokenId[ids[i]];
if (sERC20Token == address(0)) revert SYNTHETIC_ERC20_NOT_REGISTERED();
/// @dev an approval is needed on each sERC20 to burn
IsERC20(sERC20Token).burn(owner, msg.sender, amounts[i]);
address aERC20Token = aErc20TokenId[ids[i]];
if (aERC20Token == address(0)) revert AERC20_NOT_REGISTERED();
/// @dev an approval is needed on each aERC20 to burn
IaERC20(aERC20Token).burn(owner, msg.sender, amounts[i]);
}

_batchMint(owner, msg.sender, ids, amounts, bytes(""));
Expand All @@ -307,28 +307,28 @@ abstract contract ERC1155A is IERC1155A, IERC1155Errors {
/// @dev an approval is needed to burn
_burn(owner, msg.sender, id, amount);

address sERC20Token = synthethicTokenId[id];
if (sERC20Token == address(0)) revert SYNTHETIC_ERC20_NOT_REGISTERED();
address aERC20Token = aErc20TokenId[id];
if (aERC20Token == address(0)) revert AERC20_NOT_REGISTERED();

IsERC20(sERC20Token).mint(owner, amount);
IaERC20(aERC20Token).mint(owner, amount);
emit TransmutedToERC20(owner, id, amount);
}

/// @inheritdoc IERC1155A
function transmuteToERC1155A(address owner, uint256 id, uint256 amount) external override {
address sERC20Token = synthethicTokenId[id];
if (sERC20Token == address(0)) revert SYNTHETIC_ERC20_NOT_REGISTERED();
address aERC20Token = aErc20TokenId[id];
if (aERC20Token == address(0)) revert AERC20_NOT_REGISTERED();

/// @dev an approval is needed to burn
IsERC20(sERC20Token).burn(owner, msg.sender, amount);
IaERC20(aERC20Token).burn(owner, msg.sender, amount);

_mint(owner, msg.sender, id, amount, bytes(""));

emit TransmutedToERC1155A(owner, id, amount);
}

function getSyntheticTokenAddress(uint256 id) external view virtual override returns (address) {
return synthethicTokenId[id];
function getERC20TokenAddress(uint256 id) external view virtual override returns (address) {
return aErc20TokenId[id];
}

///////////////////////////////////////////////////////////////////////////
Expand All @@ -355,9 +355,9 @@ abstract contract ERC1155A is IERC1155A, IERC1155Errors {
return _totalSupply[id] > 0;
}

/// @dev handy helper to check if a SERC20 is registered
function sERC20Exists(uint256 id) external view virtual returns (bool) {
return synthethicTokenId[id] != address(0);
/// @dev handy helper to check if a AERC20 is registered
function aERC20Exists(uint256 id) external view virtual returns (bool) {
return aErc20TokenId[id] != address(0);
}

/*//////////////////////////////////////////////////////////////
Expand All @@ -377,7 +377,7 @@ abstract contract ERC1155A is IERC1155A, IERC1155Errors {

/// @notice Internal safeTranferFrom function called after all checks from the public function are done
/// @dev Notice `operator` param. It's msg.sender to the safeTransferFrom function. Function is specific to
/// SuperForm singleId approve logic.
/// @dev singleId approve logic.
function _safeTransferFrom(
address operator,
address from,
Expand Down Expand Up @@ -525,8 +525,8 @@ abstract contract ERC1155A is IERC1155A, IERC1155Errors {
emit TransferSingle(operator, from, address(0), id, amount);
}

/// @dev allows a developer to integrate their logic to create an sERC20
function _registerSERC20(uint256 id) internal virtual returns (address syntheticToken);
/// @dev allows a developer to integrate their logic to create an aERC20
function _registerAERC20(uint256 id) internal virtual returns (address aErc20Token);

/// @dev Implementation copied from openzeppelin-contracts/ERC1155 with new custom error logic and revert on
/// transfer to address 0
Expand Down
14 changes: 7 additions & 7 deletions src/sERC20.sol → src/aERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
pragma solidity ^0.8.23;

import { ERC20 } from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
import { IsERC20 } from "./interfaces/IsERC20.sol";
/// @title sERC20
import { IaERC20 } from "./interfaces/IaERC20.sol";
/// @title aERC20
/// @author Zeropoint Labs.
/// @dev Synthetic ERC20 tokens out of 1155a
/// @dev ERC20 tokens out of 1155a

contract sERC20 is ERC20, IsERC20 {
contract aERC20 is ERC20, IaERC20 {
address public immutable ERC1155A;
uint8 private immutable tokenDecimals;

Expand All @@ -25,19 +25,19 @@ contract sERC20 is ERC20, IsERC20 {
tokenDecimals = decimals_;
}

/// inheritdoc IsERC20
/// inheritdoc IaERC20
function mint(address owner, uint256 amount) external override onlyTokenSplitter {
_mint(owner, amount);
}

/// inheritdoc IsERC20
/// inheritdoc IaERC20
function burn(address owner, address operator, uint256 amount) external override onlyTokenSplitter {
if (owner != operator) _spendAllowance(owner, operator, amount);

_burn(owner, amount);
}

/// inheritdoc IsERC20
/// inheritdoc IaERC20
function decimals() public view virtual override returns (uint8) {
return tokenDecimals;
}
Expand Down
38 changes: 19 additions & 19 deletions src/interfaces/IERC1155A.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ interface IERC1155A is IERC1155 {
/// @dev if allowance is lower than amount for the operation
error NOT_ENOUGH_ALLOWANCE();

/// @dev Thrown when SERC20 was already registered
error SYNTHETIC_ERC20_ALREADY_REGISTERED();
/// @dev Thrown when AERC20 was already registered
error AERC20_ALREADY_REGISTERED();

/// @dev Thrown when SERC20 was not registered
error SYNTHETIC_ERC20_NOT_REGISTERED();
/// @dev Thrown when AERC20 was not registered
error AERC20_NOT_REGISTERED();

/// @dev allowance amount cannot be decreased below zero
error DECREASED_ALLOWANCE_BELOW_ZERO();
Expand All @@ -42,7 +42,7 @@ interface IERC1155A is IERC1155 {
/// @dev forbids transfers to address 0
error TRANSFER_TO_ADDRESS_ZERO();

/// @dev forbids registering a serc20 if no associated erc1155a has been minted yet first
/// @dev forbids registering a saErc20 if no associated erc1155a has been minted yet first
error ID_NOT_MINTED_YET();
/*//////////////////////////////////////////////////////////////
SINGLE APPROVE
Expand Down Expand Up @@ -93,17 +93,17 @@ interface IERC1155A is IERC1155 {
returns (bool);

/*//////////////////////////////////////////////////////////////
SERC20 AND TRANSMUTE LOGIC
AERC20 AND TRANSMUTE LOGIC
//////////////////////////////////////////////////////////////*/

/// @dev Function set to virtual so that implementing protocols may introduce RBAC here or perform other changes
/// @notice payable to allow any implementing cross-chain protocol to be paid for fees for relaying this action to
/// various chain
/// @param id of the ERC1155 to create a synthetic ERC20 for
function registerSERC20(uint256 id) external payable returns (address);
/// @param id of the ERC1155 to create a ERC20 for
function registerAERC20(uint256 id) external payable returns (address);

/// @notice Use transmuteBatchToERC20 to transmute multiple ERC1155 ids into separate ERC20
/// Easier to transmute to 1155A than to transmute back to erc20 because of ERC1155 beauty!
/// Easier to transmute to 1155A than to transmute back to aErc20 because of ERC1155 beauty!
/// @param onBehalfOf address of the user on whose behalf this transmutation is happening
/// @param ids ids of the ERC1155A to transmute
/// @param amounts amounts of the ERC1155A to transmute
Expand All @@ -116,26 +116,26 @@ interface IERC1155A is IERC1155 {
function transmuteBatchToERC1155A(address onBehalfOf, uint256[] memory ids, uint256[] memory amounts) external;

/// @param onBehalfOf address of the user on whose behalf this transmutation is happening
/// @param id id of the ERC20s to transmute to erc20
/// @param amount amount of the ERC20s to transmute to erc20
/// @param id id of the ERC20s to transmute to aErc20
/// @param amount amount of the ERC20s to transmute to aErc20
function transmuteToERC20(address onBehalfOf, uint256 id, uint256 amount) external;

/// @param onBehalfOf address of the user on whose behalf this transmutation is happening
/// @param id id of the ERC20s to transmute to erc1155
/// @param amount amount of the ERC20s to transmute to erc1155
function transmuteToERC1155A(address onBehalfOf, uint256 id, uint256 amount) external;

/// @notice Public getter for the address of the synthetic token for a given ERC1155 id
/// @param id id of the ERC1155 to get the synthetic token address for
/// @return sERC20 address of the synthetic token for the given ERC1155 id
function getSyntheticTokenAddress(uint256 id) external view returns (address sERC20);
/// @notice Public getter for the address of the aErc20 token for a given ERC1155 id
/// @param id id of the ERC1155 to get the aErc20 token address for
/// @return aERC20 address of the aErc20 token for the given ERC1155 id
function getERC20TokenAddress(uint256 id) external view returns (address aERC20);

/*//////////////////////////////////////////////////////////////
METADATA
//////////////////////////////////////////////////////////////*/

/// @dev Compute return string from baseURI set for this contract and unique vaultId
function uri(uint256 superFormId) external view returns (string memory);
function uri(uint256 id) external view returns (string memory);

/*//////////////////////////////////////////////////////////////
SUPPLY GETTERS
Expand All @@ -148,7 +148,7 @@ interface IERC1155A is IERC1155 {
/// @dev determines based on total supply for the id
function exists(uint256 id) external view returns (bool);

/// @dev handy helper to check if a SERC20 is registered
/// @param id of the ERC1155 to check if a synthetic ERC20 exists for
function sERC20Exists(uint256 id) external view returns (bool);
/// @dev handy helper to check if a AERC20 is registered
/// @param id of the ERC1155 to check if a AERC20 exists for
function aERC20Exists(uint256 id) external view returns (bool);
}
6 changes: 3 additions & 3 deletions src/interfaces/IsERC20.sol → src/interfaces/IaERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ pragma solidity ^0.8.23;

import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";

/// @title sERC20
/// @title aERC20
/// @author Zeropoint Labs.
/// @dev Synthetic ERC20 tokens out of 1155a
interface IsERC20 is IERC20 {
/// @dev ERC20 tokens out of 1155a
interface IaERC20 is IERC20 {
/// @dev allows msg.sender set in constructor to mint
/// @param owner address of the owner of the tokens
/// @param amount amount of tokens to mint
Expand Down
Loading

0 comments on commit 3345669

Please sign in to comment.