Skip to content

Commit

Permalink
Major bump to comment lines ratio (#73)
Browse files Browse the repository at this point in the history
* OrderProcessor code comments

* BuyOrderIssuer code comments

* DirectBuyIssuer code comments

* IOrderBridge code comments

* OrderFees code comments

* Order lifecycle event descriptions

* SellOrderProcessor code comments

* BridgedERC20 code comments

* IMintBurn code comments

* TransferRestrictor code comments

* events comments

* error descriptions and comments

* Opinionation
  • Loading branch information
jaketimothy authored Jun 15, 2023
1 parent f1ad904 commit 9e62f88
Show file tree
Hide file tree
Showing 14 changed files with 406 additions and 138 deletions.
72 changes: 36 additions & 36 deletions .gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,48 @@ BridgedERC20Test:testBurn() (gas: 120710)
BridgedERC20Test:testBurnUnauthorizedReverts() (gas: 149477)
BridgedERC20Test:testMint() (gas: 85270)
BridgedERC20Test:testMintUnauthorizedReverts() (gas: 70722)
BridgedERC20Test:testSetDisclosures(string) (runs: 518, μ: 61182, ~: 68688)
BridgedERC20Test:testSetName(string) (runs: 518, μ: 60148, ~: 68654)
BridgedERC20Test:testSetRestrictor(address) (runs: 518, μ: 19502, ~: 19508)
BridgedERC20Test:testSetSymbol(string) (runs: 518, μ: 61557, ~: 68720)
BridgedERC20Test:testSetDisclosures(string) (runs: 518, μ: 60664, ~: 68688)
BridgedERC20Test:testSetName(string) (runs: 518, μ: 60972, ~: 68654)
BridgedERC20Test:testSetRestrictor(address) (runs: 518, μ: 19508, ~: 19508)
BridgedERC20Test:testSetSymbol(string) (runs: 518, μ: 60445, ~: 68720)
BridgedERC20Test:testTransfer() (gas: 102095)
BridgedERC20Test:testTransferRestrictedFromReverts() (gas: 121429)
BridgedERC20Test:testTransferRestrictedToReverts() (gas: 123593)
BuyOrderIssuerTest:testCancelOrder(uint128,uint128,string) (runs: 518, μ: 370916, ~: 378792)
BuyOrderIssuerTest:testCancelOrderNotFoundReverts() (gas: 54694)
BuyOrderIssuerTest:testFillOrder(uint128,uint128,uint256) (runs: 518, μ: 338614, ~: 382418)
BuyOrderIssuerTest:testFillorderNoOrderReverts() (gas: 54549)
BuyOrderIssuerTest:testFulfillOrder(uint128,uint256) (runs: 518, μ: 342504, ~: 344288)
BuyOrderIssuerTest:testGetInputValue(uint64,uint64,uint128) (runs: 518, μ: 628977, ~: 632845)
BuyOrderIssuerTest:testInitialize(address,address) (runs: 518, μ: 7013243, ~: 7013243)
BuyOrderIssuerTest:testInitializeZeroOwnerReverts() (gas: 3449093)
BuyOrderIssuerTest:testInitializeZeroTreasuryReverts() (gas: 3523035)
BuyOrderIssuerTest:testNoFees(uint128) (runs: 518, μ: 20350, ~: 20350)
BuyOrderIssuerTest:testRequestCancel() (gas: 261898)
BuyOrderIssuerTest:testCancelOrder(uint128,uint128,string) (runs: 518, μ: 362197, ~: 369592)
BuyOrderIssuerTest:testCancelOrderNotFoundReverts() (gas: 37594)
BuyOrderIssuerTest:testFillOrder(uint128,uint128,uint256) (runs: 518, μ: 319851, ~: 362518)
BuyOrderIssuerTest:testFillorderNoOrderReverts() (gas: 37449)
BuyOrderIssuerTest:testFulfillOrder(uint128,uint256) (runs: 518, μ: 331186, ~: 332850)
BuyOrderIssuerTest:testGetInputValue(uint64,uint64,uint128) (runs: 518, μ: 629051, ~: 632930)
BuyOrderIssuerTest:testInitialize(address,address) (runs: 518, μ: 7081363, ~: 7081363)
BuyOrderIssuerTest:testInitializeZeroOwnerReverts() (gas: 3472134)
BuyOrderIssuerTest:testInitializeZeroTreasuryReverts() (gas: 3471791)
BuyOrderIssuerTest:testNoFees(uint128) (runs: 518, μ: 20435, ~: 20435)
BuyOrderIssuerTest:testRequestCancel() (gas: 241998)
BuyOrderIssuerTest:testRequestCancelNotFoundReverts() (gas: 27787)
BuyOrderIssuerTest:testRequestCancelNotRequesterReverts() (gas: 255440)
BuyOrderIssuerTest:testRequestOrder(uint128) (runs: 518, μ: 208947, ~: 272336)
BuyOrderIssuerTest:testRequestOrderCollisionReverts() (gas: 257327)
BuyOrderIssuerTest:testRequestOrderPausedReverts() (gas: 56734)
BuyOrderIssuerTest:testRequestOrderUnsupportedAssetReverts(address) (runs: 518, μ: 113169, ~: 113169)
BuyOrderIssuerTest:testRequestOrderUnsupportedPaymentReverts(address) (runs: 518, μ: 115636, ~: 115636)
BuyOrderIssuerTest:testRequestOrderWithPermit() (gas: 333250)
BuyOrderIssuerTest:testRequestOrderWithPermitCollisionReverts() (gas: 299841)
BuyOrderIssuerTest:testSetFees(address) (runs: 518, μ: 24723, ~: 24723)
BuyOrderIssuerTest:testRequestCancelNotRequesterReverts() (gas: 235540)
BuyOrderIssuerTest:testRequestOrder(uint128) (runs: 518, μ: 194228, ~: 252436)
BuyOrderIssuerTest:testRequestOrderCollisionReverts() (gas: 240227)
BuyOrderIssuerTest:testRequestOrderPausedReverts() (gas: 39634)
BuyOrderIssuerTest:testRequestOrderUnsupportedAssetReverts(address) (runs: 518, μ: 96069, ~: 96069)
BuyOrderIssuerTest:testRequestOrderUnsupportedPaymentReverts(address) (runs: 518, μ: 98536, ~: 98536)
BuyOrderIssuerTest:testRequestOrderWithPermit() (gas: 313350)
BuyOrderIssuerTest:testRequestOrderWithPermitCollisionReverts() (gas: 282741)
BuyOrderIssuerTest:testSetFees(address) (runs: 518, μ: 24903, ~: 24903)
BuyOrderIssuerTest:testSetOrdersPaused(bool) (runs: 518, μ: 22686, ~: 21789)
BuyOrderIssuerTest:testSetTreasury(address) (runs: 518, μ: 25267, ~: 25267)
BuyOrderIssuerTest:testSetTreasuryZeroReverts() (gas: 15982)
DirectBuyIssuerTest:testCancelOrder(uint128,uint128,string) (runs: 518, μ: 389509, ~: 397094)
DirectBuyIssuerTest:testCancelOrderUnreturnedEscrowReverts(uint128,uint128) (runs: 518, μ: 323685, ~: 323685)
DirectBuyIssuerTest:testFillOrder(uint128,uint128,uint128,uint256) (runs: 518, μ: 356933, ~: 343592)
DirectBuyIssuerTest:testReturnEscrow(uint128,uint256) (runs: 518, μ: 329431, ~: 324973)
DirectBuyIssuerTest:testTakeEscrow(uint128,uint256) (runs: 518, μ: 301280, ~: 286699)
DirectBuyIssuerTest:testCancelOrder(uint128,uint128,string) (runs: 518, μ: 379720, ~: 387890)
DirectBuyIssuerTest:testCancelOrderUnreturnedEscrowReverts(uint128,uint128) (runs: 518, μ: 306585, ~: 306585)
DirectBuyIssuerTest:testFillOrder(uint128,uint128,uint128,uint256) (runs: 518, μ: 337215, ~: 326489)
DirectBuyIssuerTest:testReturnEscrow(uint128,uint256) (runs: 518, μ: 309278, ~: 305073)
DirectBuyIssuerTest:testTakeEscrow(uint128,uint256) (runs: 518, μ: 281830, ~: 266799)
OrderFeesTest:testRecoverInputValueFromRemaining(uint64,uint128) (runs: 518, μ: 22551, ~: 22896)
OrderFeesTest:testSetFee(uint64,uint64,uint8,uint128) (runs: 518, μ: 589862, ~: 726435)
OrderFeesTest:testSetFee(uint64,uint64,uint8,uint128) (runs: 518, μ: 592375, ~: 726435)
OrderFeesTest:testUSDC() (gas: 15635)
SellOrderProcessorTest:testCancelOrder(uint128,uint128,uint128,string) (runs: 518, μ: 399734, ~: 423048)
SellOrderProcessorTest:testFillOrder(uint128,uint128,uint256) (runs: 518, μ: 339591, ~: 325645)
SellOrderProcessorTest:testFulfillOrder(uint128,uint256) (runs: 518, μ: 372815, ~: 385584)
SellOrderProcessorTest:testNoFees(uint128) (runs: 518, μ: 19436, ~: 19436)
SellOrderProcessorTest:testRequestOrder(uint128) (runs: 518, μ: 253696, ~: 259604)
TransferRestrictorTest:testRestrictUnrestrict(address) (runs: 518, μ: 36984, ~: 36977)
SellOrderProcessorTest:testCancelOrder(uint128,uint128,uint128,string) (runs: 518, μ: 391551, ~: 413855)
SellOrderProcessorTest:testFillOrder(uint128,uint128,uint256) (runs: 518, μ: 322047, ~: 308545)
SellOrderProcessorTest:testFulfillOrder(uint128,uint256) (runs: 518, μ: 361425, ~: 374145)
SellOrderProcessorTest:testNoFees(uint128) (runs: 518, μ: 19521, ~: 19521)
SellOrderProcessorTest:testRequestOrder(uint128) (runs: 518, μ: 233882, ~: 239704)
TransferRestrictorTest:testRestrictUnrestrict(address) (runs: 518, μ: 36985, ~: 36977)
51 changes: 44 additions & 7 deletions src/BridgedERC20.sol
Original file line number Diff line number Diff line change
@@ -1,31 +1,48 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

// solady ERC20 allows EIP-2612 domain separator with `name` changes
import {ERC20} from "solady/tokens/ERC20.sol";
import {AccessControlDefaultAdminRules} from
"openzeppelin-contracts/contracts/access/AccessControlDefaultAdminRules.sol";
import {ITransferRestrictor} from "./ITransferRestrictor.sol";

/// @notice ERC20 with minter and blacklist.
/// @notice Core token contract for bridged assets.
/// @author Dinari (https://github.com/dinaricrypto/issuer-contracts/blob/main/src/BridgedERC20.sol)
/// ERC20 with minter, burner, and blacklist
/// Uses solady ERC20 which allows EIP-2612 domain separator with `name` changes
contract BridgedERC20 is ERC20, AccessControlDefaultAdminRules {
/// ------------------ Events ------------------ ///

/// @dev Emitted when `name` is set
event NameSet(string name);
/// @dev Emitted when `symbol` is set
event SymbolSet(string symbol);
/// @dev Emitted when `disclosures` URI is set
event DisclosuresSet(string disclosures);
/// @dev Emitted when transfer restrictor contract is set
event TransferRestrictorSet(ITransferRestrictor indexed transferRestrictor);

/// ------------------ Constants ------------------ ///

/// @notice Role for approved minters
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
/// @notice Role for approved burners
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");

string internal _name;
string internal _symbol;
/// ------------------ State ------------------ ///

/// @dev URI to disclosure information
/// @dev Token name
string private _name;
/// @dev Token symbol
string private _symbol;

/// @notice URI to disclosure information
string public disclosures;
/// @dev Contract to restrict transfers
/// @notice Contract to restrict transfers
ITransferRestrictor public transferRestrictor;

/// ------------------ Initialization ------------------ ///

constructor(
address owner,
string memory name_,
Expand All @@ -39,34 +56,50 @@ contract BridgedERC20 is ERC20, AccessControlDefaultAdminRules {
transferRestrictor = transferRestrictor_;
}

/// ------------------ Getters ------------------ ///

/// @notice Returns the name of the token
function name() public view virtual override returns (string memory) {
return _name;
}

/// @notice Returns the symbol of the token
function symbol() public view virtual override returns (string memory) {
return _symbol;
}

/// ------------------ Setters ------------------ ///

/// @notice Set token name
/// @dev Only callable by owner
function setName(string calldata name_) external onlyRole(DEFAULT_ADMIN_ROLE) {
_name = name_;
emit NameSet(name_);
}

/// @notice Set token symbol
/// @dev Only callable by owner
function setSymbol(string calldata symbol_) external onlyRole(DEFAULT_ADMIN_ROLE) {
_symbol = symbol_;
emit SymbolSet(symbol_);
}

/// @notice Set disclosures URI
/// @dev Only callable by owner
function setDisclosures(string calldata disclosures_) external onlyRole(DEFAULT_ADMIN_ROLE) {
disclosures = disclosures_;
emit DisclosuresSet(disclosures_);
}

/// @notice Set transfer restrictor contract
/// @dev Only callable by owner
function setTransferRestrictor(ITransferRestrictor restrictor) external onlyRole(DEFAULT_ADMIN_ROLE) {
transferRestrictor = restrictor;
emit TransferRestrictorSet(restrictor);
}

/// ------------------ Minting and Burning ------------------ ///

/// @notice Mint tokens
/// @param to Address to mint tokens to
/// @param value Amount of tokens to mint
Expand All @@ -82,12 +115,16 @@ contract BridgedERC20 is ERC20, AccessControlDefaultAdminRules {
_burn(msg.sender, value);
}

/// ------------------ Transfers ------------------ ///

/// @inheritdoc ERC20
function _beforeTokenTransfer(address from, address to, uint256) internal virtual override {
// restrictions ignored for minting and burning
// Restrictions ignored for minting and burning
if (from == address(0) || to == address(0) || address(transferRestrictor) == address(0)) {
return;
}

// Check transfer restrictions
transferRestrictor.requireNotRestricted(from, to);
}
}
8 changes: 7 additions & 1 deletion src/IMintBurn.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

/// @notice
/// @notice Interface for token minting and burning
/// @author Dinari (https://github.com/dinaricrypto/issuer-contracts/blob/main/src/IMintBurn.sol)
/// Implemented by BridgedERC20
interface IMintBurn {
/// @notice Mint new tokens
/// @param to Address to mint tokens to
/// @param value Amount of tokens to mint
function mint(address to, uint256 value) external;

/// @notice Burn tokens
/// @param value Amount of tokens to burn
function burn(uint256 value) external;
}
2 changes: 1 addition & 1 deletion src/ITransferRestrictor.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

/// @notice
/// @notice Interface for transfer restriction contract
/// @author Dinari (https://github.com/dinaricrypto/issuer-contracts/blob/main/src/ITransferRestrictor.sol)
interface ITransferRestrictor {
/// @notice Checks if the transfer is allowed
Expand Down
28 changes: 20 additions & 8 deletions src/TransferRestrictor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,54 @@
pragma solidity ^0.8.19;

import {Ownable2Step} from "openzeppelin-contracts/contracts/access/Ownable2Step.sol";
import "./ITransferRestrictor.sol";
import {ITransferRestrictor} from "./ITransferRestrictor.sol";

/// @notice Enforces transfer restrictions
/// @author Dinari (https://github.com/dinaricrypto/issuer-contracts/blob/main/src/TransferRestrictor.sol)
/// Maintains a single `owner` who can add or remove accounts from `blacklist`
contract TransferRestrictor is Ownable2Step, ITransferRestrictor {
/// ------------------ Types ------------------ ///

/// @dev Account is restricted
error AccountRestricted();

/// @dev Emitted when `account` is added to `blacklist`
event Restricted(address indexed account);
/// @dev Emitted when `account` is removed from `blacklist`
event Unrestricted(address indexed account);

/// @notice If an account is listed, it cannot send or receive tokens
/// ------------------ State ------------------ ///

/// @notice Accounts in `blacklist` cannot send or receive tokens
mapping(address => bool) public blacklist;

/// ------------------ Initialization ------------------ ///

constructor(address owner) {
_transferOwnership(owner);
}

/*//////////////////////////////////////////////////////////////
OPERATIONS CALLED BY OWNER
//////////////////////////////////////////////////////////////*/
/// ------------------ Setters ------------------ ///

/// @notice Restrict `account` from sending or receiving tokens
/// @dev Does not check if `account` is restricted
function restrict(address account) external onlyOwner {
blacklist[account] = true;
emit Restricted(account);
}

/// @notice Unrestrict `account` from sending or receiving tokens
/// @dev Does not check if `account` is restricted
function unrestrict(address account) external onlyOwner {
blacklist[account] = false;
emit Unrestricted(account);
}

/*//////////////////////////////////////////////////////////////
USED BY INTERFACE
//////////////////////////////////////////////////////////////*/
/// ------------------ Transfer Restriction ------------------ ///

/// @inheritdoc ITransferRestrictor
function requireNotRestricted(address from, address to) external view virtual {
// Check if either account is restricted
if (blacklist[from] || blacklist[to]) {
revert AccountRestricted();
}
Expand Down
Loading

0 comments on commit 9e62f88

Please sign in to comment.