Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feat/custom-token-reg…
Browse files Browse the repository at this point in the history
…istars
  • Loading branch information
Foivos committed Oct 3, 2023
2 parents 1127093 + 7311951 commit 943de1f
Show file tree
Hide file tree
Showing 25 changed files with 311 additions and 142 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

pragma solidity ^0.8.0;

import { IAxelarGateway } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol';
import { IAxelarGasService } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol';
import { AxelarExecutable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol';
import { SafeTokenTransferFrom } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/utils/SafeTransfer.sol';
Expand Down
2 changes: 1 addition & 1 deletion contracts/interchain-token/InterchainToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ abstract contract InterchainToken is IInterchainToken, ERC20 {
) external payable {
uint256 _allowance = allowance[sender][msg.sender];

if (_allowance != type(uint256).max) {
if (_allowance != UINT256_MAX) {
_approve(sender, msg.sender, _allowance - amount);
}

Expand Down
25 changes: 25 additions & 0 deletions contracts/interfaces/IERC20BurnableFrom.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20BurnableFrom {
/**
* @notice Function to burn tokens from a burn deposit address
* @notice It is needed to support legacy Axelar Gateway tokens
* @dev Can only be called after token is transferred to a deposit address.
* @param salt The address that will have its tokens burnt
*/
function burn(bytes32 salt) external;

/**
* @notice Function to burn tokens
* @notice Requires the caller to have allowance for `amount` on `from`
* @dev Can only be called by the distributor address.
* @param from The address that will have its tokens burnt
* @param amount The amount of tokens to burn
*/
function burnFrom(address from, uint256 amount) external;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20BurnableMintable {
interface IERC20MintableBurnable {
/**
* @notice Function to mint new tokens
* Can only be called by the distributor address.
* @dev Can only be called by the distributor address.
* @param to The address that will receive the minted tokens
* @param amount The amount of tokens to mint
*/
function mint(address to, uint256 amount) external;

/**
* @notice Function to burn tokens
* Can only be called by the distributor address.
* @dev Can only be called by the distributor address.
* @param from The address that will have its tokens burnt
* @param amount The amount of tokens to burn
*/
Expand Down
12 changes: 5 additions & 7 deletions contracts/interfaces/IInterchainTokenService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

pragma solidity ^0.8.0;

import { IAxelarGateway } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol';
import { IAxelarExecutable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarExecutable.sol';

import { IExpressCallHandler } from './IExpressCallHandler.sol';
import { ITokenManagerDeployer } from './ITokenManagerDeployer.sol';
import { ITokenManagerType } from './ITokenManagerType.sol';
import { IPausable } from './IPausable.sol';
import { IMulticall } from './IMulticall.sol';
Expand All @@ -30,9 +28,9 @@ interface IInterchainTokenService is ITokenManagerType, IExpressCallHandler, IAx
error AlreadyExecuted(bytes32 commandId);
error InvalidExpressSelector();

event TokenSent(bytes32 tokenId, string destinationChain, bytes destinationAddress, uint256 indexed amount);
event TokenSent(bytes32 indexed tokenId, string destinationChain, bytes destinationAddress, uint256 indexed amount);
event TokenSentWithData(
bytes32 tokenId,
bytes32 indexed tokenId,
string destinationChain,
bytes destinationAddress,
uint256 indexed amount,
Expand Down Expand Up @@ -62,19 +60,19 @@ interface IInterchainTokenService is ITokenManagerType, IExpressCallHandler, IAx
uint8 tokenDecimals,
bytes distributor,
bytes mintTo,
uint256 mintAmount,
uint256 indexed mintAmount,
bytes operator,
string destinationChain,
uint256 indexed gasValue
);
event TokenManagerDeployed(bytes32 indexed tokenId, TokenManagerType indexed tokenManagerType, bytes params);
event StandardizedTokenDeployed(
bytes32 indexed tokenId,
address distributor,
address indexed distributor,
string name,
string symbol,
uint8 decimals,
uint256 mintAmount,
uint256 indexed mintAmount,
address mintTo
);
event CustomTokenIdClaimed(bytes32 indexed tokenId, address indexed deployer, bytes32 indexed salt);
Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IPausable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pragma solidity ^0.8.0;
* if a pause condition is activated.
*/
interface IPausable {
event PausedSet(bool paused);
event PausedSet(bool indexed paused);

error Paused();

Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IStandardizedToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.0;

import { IInterchainToken } from './IInterchainToken.sol';
import { IDistributable } from './IDistributable.sol';
import { IERC20BurnableMintable } from './IERC20BurnableMintable.sol';
import { IERC20MintableBurnable } from './IERC20MintableBurnable.sol';
import { ITokenManager } from './ITokenManager.sol';
import { IERC20Named } from './IERC20Named.sol';

Expand Down
3 changes: 2 additions & 1 deletion contracts/interfaces/ITokenManagerType.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ pragma solidity ^0.8.0;
*/
interface ITokenManagerType {
enum TokenManagerType {
LOCK_UNLOCK,
MINT_BURN,
MINT_BURN_FROM,
LOCK_UNLOCK,
LOCK_UNLOCK_FEE_ON_TRANSFER,
LIQUIDITY_POOL
}
Expand Down
4 changes: 2 additions & 2 deletions contracts/remote-address-validator/RemoteAddressValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ contract RemoteAddressValidator is IRemoteAddressValidator, Upgradable {
function removeTrustedAddress(string calldata sourceChain) external onlyOwner {
if (bytes(sourceChain).length == 0) revert ZeroStringLength();

remoteAddressHashes[sourceChain] = bytes32(0);
remoteAddresses[sourceChain] = '';
delete remoteAddressHashes[sourceChain];
delete remoteAddresses[sourceChain];

emit TrustedAddressRemoved(sourceChain);
}
Expand Down
11 changes: 6 additions & 5 deletions contracts/test/FeeOnTransferTokenTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ pragma solidity ^0.8.0;
import { InterchainToken } from '../interchain-token/InterchainToken.sol';
import { Distributable } from '../utils/Distributable.sol';
import { ITokenManager } from '../interfaces/ITokenManager.sol';
import { IERC20BurnableMintable } from '../interfaces/IERC20BurnableMintable.sol';
import { IERC20MintableBurnable } from '../interfaces/IERC20MintableBurnable.sol';

contract FeeOnTransferTokenTest is InterchainToken, Distributable, IERC20BurnableMintable {
contract FeeOnTransferTokenTest is InterchainToken, Distributable, IERC20MintableBurnable {
ITokenManager public tokenManager_;
bool internal tokenManagerRequiresApproval_ = true;

string public name;
string public symbol;
uint8 public decimals;
Expand All @@ -36,9 +37,9 @@ contract FeeOnTransferTokenTest is InterchainToken, Distributable, IERC20Burnabl
if (!tokenManagerRequiresApproval_) return;
address tokenManagerAddress = address(tokenManager_);
uint256 allowance_ = allowance[sender][tokenManagerAddress];
if (allowance_ != type(uint256).max) {
if (allowance_ > type(uint256).max - amount) {
allowance_ = type(uint256).max - amount;
if (allowance_ != UINT256_MAX) {
if (allowance_ > UINT256_MAX - amount) {
allowance_ = UINT256_MAX - amount;
}

_approve(sender, tokenManagerAddress, allowance_ + amount);
Expand Down
10 changes: 5 additions & 5 deletions contracts/test/InterchainTokenTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ pragma solidity ^0.8.0;
import { InterchainToken } from '../interchain-token/InterchainToken.sol';
import { Distributable } from '../utils/Distributable.sol';
import { ITokenManager } from '../interfaces/ITokenManager.sol';
import { IERC20BurnableMintable } from '../interfaces/IERC20BurnableMintable.sol';
import { IERC20MintableBurnable } from '../interfaces/IERC20MintableBurnable.sol';

contract InterchainTokenTest is InterchainToken, Distributable, IERC20BurnableMintable {
contract InterchainTokenTest is InterchainToken, Distributable, IERC20MintableBurnable {
ITokenManager public tokenManager_;
bool internal tokenManagerRequiresApproval_ = true;
string public name;
Expand Down Expand Up @@ -36,9 +36,9 @@ contract InterchainTokenTest is InterchainToken, Distributable, IERC20BurnableMi
if (!tokenManagerRequiresApproval_) return;
address tokenManagerAddress = address(tokenManager_);
uint256 allowance_ = allowance[sender][tokenManagerAddress];
if (allowance_ != type(uint256).max) {
if (allowance_ > type(uint256).max - amount) {
allowance_ = type(uint256).max - amount;
if (allowance_ != UINT256_MAX) {
if (allowance_ > UINT256_MAX - amount) {
allowance_ = UINT256_MAX - amount;
}

_approve(sender, tokenManagerAddress, allowance_ + amount);
Expand Down
3 changes: 2 additions & 1 deletion contracts/token-implementations/ERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ contract ERC20 is IERC20 {
mapping(address => mapping(address => uint256)) public override allowance;

uint256 public override totalSupply;
uint256 internal constant UINT256_MAX = 2 ** 256 - 1;

/**
* @dev See {IERC20-transfer}.
Expand Down Expand Up @@ -79,7 +80,7 @@ contract ERC20 is IERC20 {
function transferFrom(address sender, address recipient, uint256 amount) external virtual override returns (bool) {
uint256 _allowance = allowance[sender][msg.sender];

if (_allowance != type(uint256).max) {
if (_allowance != UINT256_MAX) {
_approve(sender, msg.sender, _allowance - amount);
}

Expand Down
21 changes: 14 additions & 7 deletions contracts/token-implementations/ERC20Permit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ abstract contract ERC20Permit is IERC20, IERC20Permit, ERC20 {
* @dev Represents hash of the EIP-712 Domain Separator.
*/
// solhint-disable-next-line var-name-mixedcase
bytes32 public DOMAIN_SEPARATOR;
bytes32 public nameHash;

string private constant EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA = '\x19\x01';

Expand All @@ -38,13 +38,20 @@ abstract contract ERC20Permit is IERC20, IERC20Permit, ERC20 {
mapping(address => uint256) public nonces;

/**
* @notice Internal function to set the domain type signature hash
* @notice Internal function to set the token name hash
* @param name The token name
*/
function _setDomainTypeSignatureHash(string memory name) internal {
DOMAIN_SEPARATOR = keccak256(
abi.encode(DOMAIN_TYPE_SIGNATURE_HASH, keccak256(bytes(name)), keccak256(bytes('1')), block.chainid, address(this))
);
function _setNameHash(string memory name) internal {
nameHash = keccak256(bytes(name));
}

/**
* @notice Calculates the DOMAIN_SEPARATOR.
* @dev This is not cached because chainid can change on chain forks.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() public view returns (bytes32 domainSeparator) {
domainSeparator = keccak256(abi.encode(DOMAIN_TYPE_SIGNATURE_HASH, nameHash, keccak256(bytes('1')), block.chainid, address(this)));
}

/**
Expand All @@ -69,7 +76,7 @@ abstract contract ERC20Permit is IERC20, IERC20Permit, ERC20 {
bytes32 digest = keccak256(
abi.encodePacked(
EIP191_PREFIX_FOR_EIP712_STRUCTURED_DATA,
DOMAIN_SEPARATOR,
DOMAIN_SEPARATOR(),
keccak256(abi.encode(PERMIT_SIGNATURE_HASH, issuer, spender, value, nonces[issuer]++, deadline))
)
);
Expand Down
8 changes: 4 additions & 4 deletions contracts/token-implementations/StandardizedToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

pragma solidity ^0.8.0;

import { IERC20BurnableMintable } from '../interfaces/IERC20BurnableMintable.sol';
import { IERC20MintableBurnable } from '../interfaces/IERC20MintableBurnable.sol';
import { ITokenManager } from '../interfaces/ITokenManager.sol';

import { InterchainToken } from '../interchain-token/InterchainToken.sol';
Expand All @@ -16,13 +16,13 @@ import { Distributable } from '../utils/Distributable.sol';
* @notice This contract implements a standardized token which extends InterchainToken functionality.
* This contract also inherits Distributable and Implementation logic.
*/
contract StandardizedToken is IERC20BurnableMintable, InterchainToken, ERC20Permit, Implementation, Distributable {
contract StandardizedToken is IERC20MintableBurnable, InterchainToken, ERC20Permit, Implementation, Distributable {
using AddressBytesUtils for bytes;

address internal tokenManager_;
string public name;
string public symbol;
uint8 public decimals;
address internal tokenManager_;

bytes32 private constant CONTRACT_ID = keccak256('standardized-token');

Expand Down Expand Up @@ -68,7 +68,7 @@ contract StandardizedToken is IERC20BurnableMintable, InterchainToken, ERC20Perm
name = tokenName;

_setDistributor(distributor_);
_setDomainTypeSignatureHash(tokenName);
_setNameHash(tokenName);
}
{
uint256 mintAmount;
Expand Down
24 changes: 20 additions & 4 deletions contracts/token-manager/TokenManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ abstract contract TokenManager is ITokenManager, Operatable, FlowLimit, Implemen

IInterchainTokenService public immutable interchainTokenService;

// uint256(keccak256('token-address')) - 1
uint256 internal constant TOKEN_ADDRESS_SLOT = 0xc4e632779a6a7838736dd7e5e6a0eadf171dd37dfb6230720e265576dfcf42ba;

/**
* @notice Constructs the TokenManager contract.
* @param interchainTokenService_ The address of the interchain token service
Expand All @@ -46,11 +49,14 @@ abstract contract TokenManager is ITokenManager, Operatable, FlowLimit, Implemen
}

/**
* @notice A function that should return the address of the token.
* Must be overridden in the inheriting contract.
* @return address address of the token.
* @dev Reads the stored token address from the predetermined storage slot
* @return tokenAddress_ The address of the token
*/
function tokenAddress() public view virtual returns (address);
function tokenAddress() public view virtual returns (address tokenAddress_) {
assembly {
tokenAddress_ := sload(TOKEN_ADDRESS_SLOT)
}
}

/**
* @notice A function that returns the token id.
Expand Down Expand Up @@ -197,6 +203,16 @@ abstract contract TokenManager is ITokenManager, Operatable, FlowLimit, Implemen
_setFlowLimit(flowLimit);
}

/**
* @dev Stores the token address in the predetermined storage slot
* @param tokenAddress_ The address of the token to store
*/
function _setTokenAddress(address tokenAddress_) internal {
assembly {
sstore(TOKEN_ADDRESS_SLOT, tokenAddress_)
}
}

/**
* @notice Transfers tokens from a specific address to this contract.
* Must be overridden in the inheriting contract.
Expand Down

This file was deleted.

Loading

0 comments on commit 943de1f

Please sign in to comment.