Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optional staking token for swap-erc20 #1209

Merged
merged 2 commits into from
Oct 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 12 additions & 16 deletions source/swap-erc20/contracts/SwapERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 {
address public protocolFeeWallet;
uint256 public discountScale;
uint256 public discountMax;
address public staking;
address public stakingToken;

/**
* @notice Constructor
Expand All @@ -56,22 +56,19 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 {
* @param _protocolFeeWallet address destination for fees
* @param _discountScale uin256 scale factor for discount
* @param _discountMax uint256 max discount percentage
* @param _staking address staking contract address
*/
constructor(
uint256 _protocolFee,
uint256 _protocolFeeLight,
address _protocolFeeWallet,
uint256 _discountScale,
uint256 _discountMax,
address _staking
uint256 _discountMax
) EIP712(DOMAIN_NAME, DOMAIN_VERSION) {
if (_protocolFee >= FEE_DIVISOR) revert InvalidFee();
if (_protocolFeeLight >= FEE_DIVISOR) revert InvalidFeeLight();
if (_protocolFeeWallet == address(0)) revert InvalidFeeWallet();
if (_discountMax > MAX_MAX) revert MaxTooHigh();
if (_discountScale > MAX_SCALE) revert ScaleTooHigh();
if (_staking == address(0)) revert InvalidStaking();

DOMAIN_CHAIN_ID = block.chainid;
DOMAIN_SEPARATOR = _domainSeparatorV4();
Expand All @@ -81,7 +78,6 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 {
protocolFeeWallet = _protocolFeeWallet;
discountMax = _discountMax;
discountScale = _discountScale;
staking = _staking;
}

/**
Expand Down Expand Up @@ -346,13 +342,13 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 {

/**
* @notice Set the staking token
* @param newstaking address Token to check balances on
* @param _stakingToken address Token to check balances on
*/
function setStaking(address newstaking) external onlyOwner {
function setStaking(address _stakingToken) external onlyOwner {
// Ensure the new staking token is not null
if (newstaking == address(0)) revert InvalidStaking();
staking = newstaking;
emit SetStaking(newstaking);
if (_stakingToken == address(0)) revert InvalidStaking();
stakingToken = _stakingToken;
emit SetStaking(_stakingToken);
}

/**
Expand Down Expand Up @@ -543,7 +539,7 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 {
}

/**
* @notice Calculates and refers fee amount
* @notice Calculates protocol fee for an account
* @param wallet address
* @param amount uint256
*/
Expand All @@ -553,9 +549,9 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 {
) public view override returns (uint256) {
// Transfer fee from signer to feeWallet
uint256 feeAmount = (amount * protocolFee) / FEE_DIVISOR;
if (feeAmount > 0) {
if (stakingToken != address(0) && feeAmount > 0) {
uint256 discountAmount = calculateDiscount(
IERC20(staking).balanceOf(wallet),
IERC20(stakingToken).balanceOf(wallet),
feeAmount
);
return feeAmount - discountAmount;
Expand Down Expand Up @@ -723,9 +719,9 @@ contract SwapERC20 is ISwapERC20, Ownable, EIP712 {
) internal {
// Transfer fee from signer to feeWallet
uint256 feeAmount = (amount * protocolFee) / FEE_DIVISOR;
if (feeAmount > 0) {
if (stakingToken != address(0) && feeAmount > 0) {
uint256 discountAmount = calculateDiscount(
IERC20(staking).balanceOf(msg.sender),
IERC20(stakingToken).balanceOf(msg.sender),
feeAmount
);
if (discountAmount > 0) {
Expand Down
73 changes: 26 additions & 47 deletions source/swap-erc20/test/SwapERC20.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ describe('SwapERC20 Unit', () => {
const REBATE_SCALE = '10'
const REBATE_MAX = '100'
const FEE_DIVISOR = '10000'
const DEFAULT_AMOUNT = '1000'
const DEFAULT_BALANCE = '10000'
const DEFAULT_AMOUNT = '10000'
const DEFAULT_BALANCE = '100000'
const STAKING_BALANCE = '10000000000'
const SWAP_FEE =
(parseInt(DEFAULT_AMOUNT) * parseInt(PROTOCOL_FEE)) / parseInt(FEE_DIVISOR)

Expand Down Expand Up @@ -117,7 +118,7 @@ describe('SwapERC20 Unit', () => {
staking = await deployMockContract(deployer, STAKING.abi)
await signerToken.mock.transferFrom.returns(true)
await senderToken.mock.transferFrom.returns(true)
await staking.mock.balanceOf.returns(10000000)
await staking.mock.balanceOf.returns(STAKING_BALANCE)

swap = await (
await ethers.getContractFactory('SwapERC20')
Expand All @@ -126,8 +127,7 @@ describe('SwapERC20 Unit', () => {
PROTOCOL_FEE_LIGHT,
protocolFeeWallet.address,
REBATE_SCALE,
REBATE_MAX,
staking.address
REBATE_MAX
)
await swap.deployed()
})
Expand All @@ -149,8 +149,7 @@ describe('SwapERC20 Unit', () => {
PROTOCOL_FEE_LIGHT,
ADDRESS_ZERO,
REBATE_SCALE,
REBATE_MAX,
staking.address
REBATE_MAX
)
).to.be.revertedWith('InvalidFeeWallet')
})
Expand All @@ -164,8 +163,7 @@ describe('SwapERC20 Unit', () => {
PROTOCOL_FEE_LIGHT,
protocolFeeWallet.address,
REBATE_SCALE,
REBATE_MAX,
staking.address
REBATE_MAX
)
).to.be.revertedWith('InvalidFee')
})
Expand All @@ -179,8 +177,7 @@ describe('SwapERC20 Unit', () => {
100000000000,
protocolFeeWallet.address,
REBATE_SCALE,
REBATE_MAX,
staking.address
REBATE_MAX
)
).to.be.revertedWith('InvalidFeeLight')
})
Expand All @@ -194,8 +191,7 @@ describe('SwapERC20 Unit', () => {
PROTOCOL_FEE_LIGHT,
protocolFeeWallet.address,
REBATE_SCALE + 1,
REBATE_MAX,
staking.address
REBATE_MAX
)
).to.be.revertedWith('ScaleTooHigh')
})
Expand All @@ -209,26 +205,10 @@ describe('SwapERC20 Unit', () => {
PROTOCOL_FEE_LIGHT,
protocolFeeWallet.address,
REBATE_SCALE,
REBATE_MAX + 1,
staking.address
REBATE_MAX + 1
)
).to.be.revertedWith('MaxTooHigh')
})

it('test invalid discount maximum', async () => {
await expect(
(
await ethers.getContractFactory('SwapERC20')
).deploy(
PROTOCOL_FEE,
PROTOCOL_FEE_LIGHT,
protocolFeeWallet.address,
REBATE_SCALE,
REBATE_MAX,
ADDRESS_ZERO
)
).to.be.revertedWith('InvalidStaking')
})
})

describe('Test setters', async () => {
Expand Down Expand Up @@ -312,23 +292,37 @@ describe('SwapERC20 Unit', () => {
})

describe('Test calculateProtocolFee', async () => {
it('test calculateProtocolFee without staking set', async () => {
const feeAmount = await swap
.connect(deployer)
.calculateProtocolFee(sender.address, DEFAULT_AMOUNT)
expect(feeAmount).to.equal((DEFAULT_AMOUNT * PROTOCOL_FEE) / FEE_DIVISOR)
})
it('test calculateProtocolFee', async () => {
const initialFeeAmount = (DEFAULT_AMOUNT * PROTOCOL_FEE) / FEE_DIVISOR
await expect(swap.connect(deployer).setStaking(staking.address)).to.emit(
swap,
'SetStaking'
)
const discount = await swap
.connect(deployer)
.calculateDiscount(10000000, initialFeeAmount)
.calculateDiscount(STAKING_BALANCE, initialFeeAmount)
const actualFeeAmount = await swap
.connect(deployer)
.calculateProtocolFee(sender.address, DEFAULT_AMOUNT)
expect(actualFeeAmount).to.equal(initialFeeAmount - discount)
})
it('test calculateProtocolFee with protocol fee as zero', async () => {
const zeroProtocolFee = 0
await expect(swap.connect(deployer).setStaking(staking.address)).to.emit(
swap,
'SetStaking'
)
await swap.connect(deployer).setProtocolFee(zeroProtocolFee)
const initialFeeAmount = (DEFAULT_AMOUNT * zeroProtocolFee) / FEE_DIVISOR
const discount = await swap
.connect(deployer)
.calculateDiscount(10000000, initialFeeAmount)
.calculateDiscount(STAKING_BALANCE, initialFeeAmount)
const actualFeeAmount = await swap
.connect(deployer)
.calculateProtocolFee(sender.address, DEFAULT_AMOUNT)
Expand Down Expand Up @@ -635,21 +629,6 @@ describe('SwapERC20 Unit', () => {
'Unauthorized'
)
})

it('test swaps gas consumption', async () => {
const order = await createSignedOrderERC20(
{
protocolFee: PROTOCOL_FEE_LIGHT,
},
signer
)

const transaction = await swap.connect(sender).swapLight(...order)
const swapReceipt = await transaction.wait()
const swapCost = swapReceipt.gasUsed
console.log(swapCost)
expect(Number(swapCost)).to.be.lessThanOrEqual(129246)
})
})

describe('Test fees', async () => {
Expand Down
24 changes: 18 additions & 6 deletions source/swap-erc20/test/SwapERC20Integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe('SwapERC20 Integration', () => {
let senderToken
let staking

let deployer
let sender
let signer
let protocolFeeWallet
Expand Down Expand Up @@ -57,7 +58,7 @@ describe('SwapERC20 Integration', () => {
})

before('get signers and deploy', async () => {
;[sender, signer, protocolFeeWallet] = await ethers.getSigners()
;[deployer, sender, signer, protocolFeeWallet] = await ethers.getSigners()

stakingToken = await (
await ethers.getContractFactory(ERC20.abi, ERC20.bytecode)
Expand Down Expand Up @@ -89,8 +90,7 @@ describe('SwapERC20 Integration', () => {
PROTOCOL_FEE_LIGHT,
protocolFeeWallet.address,
DISCOUNT_SCALE,
DISCOUNT_MAX,
staking.address
DISCOUNT_MAX
)
await swap.deployed()

Expand All @@ -101,9 +101,16 @@ describe('SwapERC20 Integration', () => {
describe('Test token holder discounts', async () => {
it('test swap without discount', async () => {
const order = await createSignedOrder({}, signer)
await expect(
await swap.connect(sender).swap(sender.address, ...order)
).to.emit(swap, 'SwapERC20')

await expect(swap.connect(deployer).setStaking(staking.address)).to.emit(
swap,
'SetStaking'
)

await expect(swap.connect(sender).swap(sender.address, ...order)).to.emit(
swap,
'SwapERC20'
)

// Expect full 30 to be taken from signer
expect(await signerToken.balanceOf(signer.address)).to.equal('989970')
Expand All @@ -121,6 +128,11 @@ describe('SwapERC20 Integration', () => {
await stakingToken.connect(sender).approve(staking.address, 10000000000)
await staking.connect(sender).stake(10000000000)

await expect(swap.connect(deployer).setStaking(staking.address)).to.emit(
swap,
'SetStaking'
)

const order = await createSignedOrder({}, signer)

await expect(
Expand Down
3 changes: 1 addition & 2 deletions source/wrapper/test/Wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ describe('Wrapper Unit Tests', () => {
PROTOCOL_FEE_LIGHT,
protocolFeeWallet.address,
REBATE_SCALE,
REBATE_MAX,
stakingToken.address
REBATE_MAX
)
await swapERC20.deployed()

Expand Down
Loading