Skip to content

Commit

Permalink
dex/{networks,testing}: Add simnet USDC
Browse files Browse the repository at this point in the history
This adds the usdc.eth and usdc.polygon assets to simnet. This is useful
for testing market making.
  • Loading branch information
martonp committed Dec 26, 2023
1 parent 2125f1f commit 07c4050
Show file tree
Hide file tree
Showing 7 changed files with 386 additions and 12 deletions.
204 changes: 204 additions & 0 deletions dex/networks/erc20/contracts/TestUSDC.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
// SPDX-License-Identifier: MIT

// This is a simplified version of OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol).

pragma solidity = 0.8.18;

contract TestUSDC {
mapping(address => uint256) private _balances;

mapping(address => mapping(address => uint256)) private _allowances;

uint256 private _totalSupply;

string private _name;
string private _symbol;

/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor() {
_name = "USD Coin";
_symbol = "USDC";
_totalSupply = 33000000000;
_balances[0x18D65FB8d60c1199bb1Ad381bE47aA692b482605] = 11000000000; // alpha
_balances[0x4F8eF3892B65ED7fc356fF473a2eF2aE5EC27A06] = 11000000000; // beta
_balances[0xd12aB7cf72CCf1f3882eC99DDc53CD415635C3bE] = 11000000000; // delta
}

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

/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}

/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 6;
}

/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}

/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}

/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address recipient, uint256 amount) public virtual returns (bool) {
_transfer(msg.sender, recipient, amount);
return true;
}

/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual returns (uint256) {
return _allowances[owner][spender];
}

/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual returns (bool) {
_approve(msg.sender, spender, amount);
return true;
}

function testApprove(address user, address spender, uint256 amount) public returns (bool) {
_approve(user, spender, amount);
return true;
}

/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* Requirements:
*
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
* - the caller must have allowance for ``sender``'s tokens of at least
* `amount`.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual returns (bool) {
_transfer(sender, recipient, amount);

uint256 currentAllowance = _allowances[sender][msg.sender];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, msg.sender, currentAllowance - amount);
}

return true;
}

/**
* Airdrop is used to mint new tokens and give them to a user.
*/
function airdrop(address recipient, uint256 amount) public virtual {
_totalSupply += amount;
_balances[recipient] += amount;
}

/**
* @dev Moves `amount` of tokens from `sender` to `recipient`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");

uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
}

/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");

_allowances[owner][spender] = amount;
}
}
13 changes: 13 additions & 0 deletions dex/networks/erc20/contracts/updatecontract.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ PKG_NAME=v${VERSION}
CONTRACT_NAME=ERC20Swap
SOLIDITY_FILE=./${CONTRACT_NAME}V${VERSION}.sol
TEST_TOKEN=./TestToken.sol
TEST_USDC=./TestUSDC.sol
if [ ! -f ${SOLIDITY_FILE} ]
then
echo "${SOLIDITY_FILE} does not exist" >&2
Expand All @@ -27,6 +28,11 @@ then
echo "${TEST_TOKEN} does not exist" >&2
exit 1
fi
if [ ! -f ${TEST_USDC} ]
then
echo "${TEST_USDC} does not exist" >&2
exit 1
fi

mkdir temp

Expand All @@ -51,6 +57,9 @@ BYTECODE=$(<./temp/${CONTRACT_NAME}.bin)
solc --bin --optimize ${TEST_TOKEN} -o ./temp
TEST_TOKEN_BYTECODE=$(<./temp/TestToken.bin)

solc --bin --optimize ${TEST_USDC} -o ./temp
TEST_USDC_BYTECODE=$(<./temp/TestUSDC.bin)

for HARNESS_PATH in "$(realpath ../../../testing/eth/harness.sh)" "$(realpath ../../../testing/polygon/harness.sh)"; do
sed -i.tmp "s/ERC20_SWAP_V${VERSION}=.*/ERC20_SWAP_V${VERSION}=\"${BYTECODE}\"/" "${HARNESS_PATH}"
# mac needs a temp file specified above.
Expand All @@ -59,6 +68,10 @@ for HARNESS_PATH in "$(realpath ../../../testing/eth/harness.sh)" "$(realpath ..
sed -i.tmp "s/TEST_TOKEN=.*/TEST_TOKEN=\"${TEST_TOKEN_BYTECODE}\"/" "${HARNESS_PATH}"
# mac needs a temp file specified above.
rm "${HARNESS_PATH}.tmp"

sed -i.tmp "s/TEST_USDC=.*/TEST_USDC=\"${TEST_USDC_BYTECODE}\"/" "${HARNESS_PATH}"
# mac needs a temp file specified above.
rm "${HARNESS_PATH}.tmp"
done

rm -fr temp
Expand Down
32 changes: 25 additions & 7 deletions dex/networks/eth/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,21 @@ var Tokens = map[uint32]*Token{
},
},
},
dex.Simnet: { // no usdc on simnet, dextt instead
Address: common.Address{},
SwapContracts: map[uint32]*SwapContract{},
dex.Simnet: {
Address: common.Address{},
SwapContracts: map[uint32]*SwapContract{
0: {
Address: common.Address{},
Gas: Gases{
Swap: 242_000,
SwapAdd: 146_400,
Redeem: 109_000,
RedeemAdd: 31_600,
Refund: 77_000,
Approve: 78_400,
Transfer: 85_100,
}},
},
},
},
},
Expand All @@ -238,14 +250,15 @@ var Tokens = map[uint32]*Token{
// simnet harness to populate swap contract and token addresses in
// ContractAddresses and Tokens.
func MaybeReadSimnetAddrs() {
MaybeReadSimnetAddrsDir("eth", ContractAddresses, MultiBalanceAddresses, Tokens[testTokenID].NetTokens[dex.Simnet])
MaybeReadSimnetAddrsDir("eth", ContractAddresses, MultiBalanceAddresses, Tokens[testTokenID].NetTokens[dex.Simnet], Tokens[usdcTokenID].NetTokens[dex.Simnet])
}

func MaybeReadSimnetAddrsDir(
dir string,
contractsAddrs map[uint32]map[dex.Network]common.Address,
multiBalandAddresses map[dex.Network]common.Address,
token *NetToken,
testToken *NetToken,
usdcToken *NetToken,
) {

usr, err := user.Current()
Expand All @@ -265,13 +278,18 @@ func MaybeReadSimnetAddrsDir(
ethSwapContractAddrFile := filepath.Join(harnessDir, "eth_swap_contract_address.txt")
tokenSwapContractAddrFile := filepath.Join(harnessDir, "erc20_swap_contract_address.txt")
testTokenContractAddrFile := filepath.Join(harnessDir, "test_token_contract_address.txt")
testUSDCSwapContractAddrFile := filepath.Join(harnessDir, "usdc_swap_contract_address.txt")
testUSDCContractAddrFile := filepath.Join(harnessDir, "test_usdc_contract_address.txt")
multiBalanceContractAddrFile := filepath.Join(harnessDir, "multibalance_address.txt")

contractsAddrs[0][dex.Simnet] = getContractAddrFromFile(ethSwapContractAddrFile)
multiBalandAddresses[dex.Simnet] = getContractAddrFromFile(multiBalanceContractAddrFile)

token.SwapContracts[0].Address = getContractAddrFromFile(tokenSwapContractAddrFile)
token.Address = getContractAddrFromFile(testTokenContractAddrFile)
testToken.SwapContracts[0].Address = getContractAddrFromFile(tokenSwapContractAddrFile)
testToken.Address = getContractAddrFromFile(testTokenContractAddrFile)

usdcToken.SwapContracts[0].Address = getContractAddrFromFile(testUSDCSwapContractAddrFile)
usdcToken.Address = getContractAddrFromFile(testUSDCContractAddrFile)
}

func getContractAddrFromFile(fileName string) (addr common.Address) {
Expand Down
19 changes: 18 additions & 1 deletion dex/networks/polygon/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,23 @@ var (
},
},
},
dex.Simnet: {
Address: common.Address{},
SwapContracts: map[uint32]*dexeth.SwapContract{
0: {
Address: common.Address{}, // Set in MaybeReadSimnetAddrs
Gas: dexeth.Gases{
Swap: 223_163,
SwapAdd: 146_399,
Redeem: 82_121,
RedeemAdd: 41_113,
Refund: 62_527,
Approve: 58_180,
Transfer: 64_539,
},
},
},
},
},
}

Expand Down Expand Up @@ -302,5 +319,5 @@ var (
// simnet harness to populate swap contract and token addresses in
// ContractAddresses and Tokens.
func MaybeReadSimnetAddrs() {
dexeth.MaybeReadSimnetAddrsDir("polygon", ContractAddresses, MultiBalanceAddresses, Tokens[testTokenID].NetTokens[dex.Simnet])
dexeth.MaybeReadSimnetAddrsDir("polygon", ContractAddresses, MultiBalanceAddresses, Tokens[testTokenID].NetTokens[dex.Simnet], Tokens[usdcTokenID].NetTokens[dex.Simnet])
}
15 changes: 15 additions & 0 deletions dex/testing/dcrdex/harness.sh
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,15 @@ if [ $ETH_ON -eq 0 ]; then
"marketBuyBuffer": 1.2,
"parcelSize": 4
},
{
"base": "BTC_simnet",
"quote": "USDC_simnet",
"lotSize": 1000000,
"rateStep": 10000,
"epochDuration": ${EPOCH_DURATION},
"marketBuyBuffer": 1.2,
"parcelSize": 4
},
{
"base": "DCR_simnet",
"quote": "DEXTT_simnet",
Expand Down Expand Up @@ -387,6 +396,12 @@ cat << EOF >> "./markets.json"
"swapConf": 2,
"configPath": "$ETH_CONFIG_PATH"
},
"USDC_simnet": {
"bip44symbol": "usdc.eth",
"network": "simnet",
"maxFeeRate": 200,
"swapConf": 2
},
"DEXTT_simnet": {
"bip44symbol": "dextt.eth",
"network": "simnet",
Expand Down
Loading

0 comments on commit 07c4050

Please sign in to comment.