Skip to content

Commit

Permalink
feat: EIP712 / updated fees
Browse files Browse the repository at this point in the history
  • Loading branch information
chentschel committed Mar 16, 2021
1 parent db89a90 commit 948abf1
Show file tree
Hide file tree
Showing 11 changed files with 162 additions and 108 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

## Main Contracts

### PerformanceCard.sol
### PerformanceCard.sol (NFTRegistry)
Performance Cards manager contract.

### BondedERC20.sol
Expand Down Expand Up @@ -35,7 +35,7 @@ FractionableERC721: 0x3D4237C443B826fc024aa462513Ac6013058E237
PerformanceCard: 0xBF5B3dF771871E76D040afE03730ea37acFec7d4
ReserveToken (sTSX): 0x457E7C683CCf8e64F1DDA0Ff0ffE6403b002e15d
Mapped sTSX: 0xdC65b2b74826d92Bf4776c461F8d48bd1f8E5502
```


1 change: 0 additions & 1 deletion contracts/bondedERC20/BondedERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ contract BondedERC20 is Ownable, ERC20 {
_reserveRatio > 1 && _reserveRatio <= 1000000,
"BondedERC20: invalid _reserveRatio"
);

reserveRatio = _reserveRatio;
}

Expand Down
106 changes: 56 additions & 50 deletions contracts/cards/PerformanceCard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ interface EIP712 {
) external returns (address);
}

// Simple ERC721 interface

interface IERC721Simple {
function ownerOf(uint256 tokenId) external view returns (address owner);
}

// Main Contract

contract PerformanceCard is Administrable, ICard, GasPriceLimited {
Expand All @@ -45,9 +39,8 @@ contract PerformanceCard is Administrable, ICard, GasPriceLimited {
uint32 public constant MATH_PRECISION = 1e4;

// Constant values for creating bonded ERC20 tokens.
uint256 public constant ERC20_INITIAL_SUPPLY = 100000e18; // 100000 units
uint256 public constant ERC20_INITIAL_POOL_SHARE = 250; // 2.5%
uint256 public constant PLATFORM_CUT = 250; // 2.5%
uint256 public constant ERC20_INITIAL_SUPPLY = 10000e18; // 10000 units
uint256 public constant PLATFORM_CUT = 50; // .5%

// Reserve Token.
IERC20 private reserveToken;
Expand Down Expand Up @@ -292,45 +285,45 @@ contract PerformanceCard is Administrable, ICard, GasPriceLimited {
)
public override gasPriceLimited
{
// require(
// nftRegistry.getBondedERC20(_tokenId) != address(0),
// "PerformanceCard: tokenId does not exist"
// );

// // Check the sender has the required sTSX balance
// _requireBalance(msgSender(), reserveToken, _paymentAmount);

// // Transfer sTSX amount to this contract using EIP712 signature
// EIP712(address(reserveToken)).transferWithSig(
// _orderSignature,
// _paymentAmount,
// keccak256(
// abi.encodePacked(_orderId, address(reserveToken), _paymentAmount)
// ),
// _expiration,
// address(this)
// );

// // transfer platform cut.
// uint256 pFee = _paymentAmount.mul(PLATFORM_CUT).div(MATH_PRECISION);
// reserveToken.safeTransfer(owner(), pFee);

// // Get effective amount after tx fees
// uint256 effectiveReserveAmount = _paymentAmount.sub(pFee);

// // The estimated amount of bonded tokens for reserve
// uint256 estimatedTokens = nftRegistry.estimateBondedERC20Tokens(
// _tokenId,
// effectiveReserveAmount
// );

// // Issue fractionables to msg sender.
// nftRegistry.mintBondedERC20(
// _tokenId,
// msgSender(),
// estimatedTokens,
// effectiveReserveAmount
// );
require(
nftRegistry.getBondedERC20(_tokenId) != address(0),
"PerformanceCard: tokenId does not exist"
);

// Check the sender has the required sTSX balance
_requireBalance(msgSender(), reserveToken, _paymentAmount);

// Transfer sTSX amount to this contract using EIP712 signature
EIP712(address(reserveToken)).transferWithSig(
_orderSignature,
_paymentAmount,
keccak256(
abi.encodePacked(_orderId, address(reserveToken), _paymentAmount)
),
_expiration,
address(this)
);

// transfer platform cut.
uint256 pFee = _paymentAmount.mul(PLATFORM_CUT).div(MATH_PRECISION);
reserveToken.safeTransfer(owner(), pFee);

// Get effective amount after tx fees
uint256 effectiveReserveAmount = _paymentAmount.sub(pFee);

// The estimated amount of bonded tokens for reserve
uint256 estimatedTokens = nftRegistry.estimateBondedERC20Tokens(
_tokenId,
effectiveReserveAmount
);

// Issue fractionables to msg sender.
nftRegistry.mintBondedERC20(
_tokenId,
msgSender(),
estimatedTokens,
effectiveReserveAmount
);
}

/**
Expand Down Expand Up @@ -400,8 +393,15 @@ contract PerformanceCard is Administrable, ICard, GasPriceLimited {
reserveAmount
);

// fees
uint256 pFee = reserveAmount.mul(PLATFORM_CUT).div(MATH_PRECISION);
reserveToken.safeTransfer(owner(), pFee);

// Get effective amount after tx fees
uint256 effectiveReserveAmount = reserveAmount.sub(pFee);

// Trade reserve to sTSX and send to liquidator
reserveToken.safeTransfer(msgSender(), reserveAmount);
reserveToken.safeTransfer(msgSender(), effectiveReserveAmount);
}

/**
Expand All @@ -426,8 +426,14 @@ contract PerformanceCard is Administrable, ICard, GasPriceLimited {
_liquidationAmount
);

// Calc fees
uint256 pFees = reserveAmount.mul(PLATFORM_CUT).div(MATH_PRECISION);

// Get effective amount after tx fees
uint256 effectiveReserveAmount = reserveAmount.sub(pFees);

// Return the expected exchange rate and slippage in 1e18 precision
expectedRate = _liquidationAmount.mul(1e18).div(reserveAmount);
expectedRate = _liquidationAmount.mul(1e18).div(effectiveReserveAmount);
slippageRate = reserveAmount.mul(1e18).div(
ERC20Manager.poolBalance(bondedToken)
);
Expand Down
2 changes: 1 addition & 1 deletion contracts/lib/ERC20Manager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import "../bondedERC20/BondedERC20.sol";
library ERC20Manager {

function deploy(
string memory _symbol,
string memory _name,
string memory _symbol,
uint256 _tokenId
)
internal returns(address)
Expand Down
26 changes: 10 additions & 16 deletions contracts/tests/EIP712.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.6.8;

contract LibEIP712Domain {
string constant internal EIP712_DOMAIN_SCHEMA =
"EIP712Domain(string name,string version,uint256 chainId,address contract)";
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)";

bytes32 constant public EIP712_DOMAIN_SCHEMA_HASH = keccak256(
abi.encodePacked(EIP712_DOMAIN_SCHEMA)
Expand All @@ -17,25 +17,19 @@ contract LibEIP712Domain {
bytes32 public EIP712_DOMAIN_HASH;

constructor () public {
EIP712_DOMAIN_HASH = keccak256(abi.encode(
EIP712_DOMAIN_SCHEMA_HASH,
keccak256(bytes(EIP712_DOMAIN_NAME)),
keccak256(bytes(EIP712_DOMAIN_VERSION)),
EIP712_DOMAIN_CHAINID,
address(this)
));
EIP712_DOMAIN_HASH = keccak256(
abi.encode(
EIP712_DOMAIN_SCHEMA_HASH,
keccak256(bytes(EIP712_DOMAIN_NAME)),
keccak256(bytes(EIP712_DOMAIN_VERSION)),
EIP712_DOMAIN_CHAINID,
address(this)
)
);
}

function hashEIP712Message(bytes32 hashStruct) internal view returns (bytes32 result) {
bytes32 domainHash = EIP712_DOMAIN_HASH;

// Assembly for more efficient computing:
// keccak256(abi.encode(
// EIP191_HEADER,
// domainHash,
// hashStruct
// ));

assembly {
// Load free memory pointer
let memPtr := mload(64)
Expand Down
11 changes: 1 addition & 10 deletions contracts/tests/Imports.sol
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,7 @@ contract ERC20Mock is ERC20Burnable, LibTokenTransferOrder {
disabledHashes[dataHash] = true;

from = ecrecovery(dataHash, sig);
_transferFrom(from, address(uint160(to)), amount);
}

/// @param from Address from where tokens are withdrawn.
/// @param to Address to where tokens are sent.
/// @param value Number of tokens to transfer.
/// @return Returns success of function call.
function _transferFrom(address from, address to, uint256 value) internal returns (bool) {
_transfer(from, to, value);

return true;
_transfer(from, to, amount);
}
}
14 changes: 3 additions & 11 deletions contracts/tests/LibTokenTransferOrder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ contract LibTokenTransferOrder is LibEIP712Domain {
string constant internal EIP712_TOKEN_TRANSFER_ORDER_SCHEMA =
"TokenTransferOrder(address spender,uint256 tokenIdOrAmount,bytes32 data,uint256 expiration)";

bytes32 constant public EIP712_TOKEN_TRANSFER_ORDER_SCHEMA_HASH =
keccak256(abi.encodePacked(EIP712_TOKEN_TRANSFER_ORDER_SCHEMA));
bytes32 constant public EIP712_TOKEN_TRANSFER_ORDER_SCHEMA_HASH = keccak256(
abi.encodePacked(EIP712_TOKEN_TRANSFER_ORDER_SCHEMA)
);

struct TokenTransferOrder {
address spender;
Expand Down Expand Up @@ -41,15 +42,6 @@ contract LibTokenTransferOrder is LibEIP712Domain {
{
bytes32 schemaHash = EIP712_TOKEN_TRANSFER_ORDER_SCHEMA_HASH;

// Assembly for more efficiently computing:
// return keccak256(abi.encode(
// schemaHash,
// spender,
// tokenIdOrAmount,
// data,
// expiration
// ));

assembly {
// Load free memory pointer
let memPtr := mload(64)
Expand Down
68 changes: 68 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"dotenv": "^8.2.0",
"eslint": "^7.9.0",
"eslint-plugin-prettier": "^3.1.4",
"eth-sig-util": "^2.5.3",
"ganache-core": "^2.11.3",
"husky": "^4.2.5",
"mocha": "^7.2.0",
Expand Down
Loading

0 comments on commit 948abf1

Please sign in to comment.