ethereumjs-util#ecsign TypeScript Examples
The following examples show how to use
ethereumjs-util#ecsign.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: KeysService.ts From affinidi-core-sdk with Apache License 2.0 | 6 votes |
async createTransactionSignature(digestHex: string, seedHex: string) {
const seed = Buffer.from(seedHex, 'hex')
const privateKey = bip32FromSeed(seed).derivePath(etheriumIdentityKey).privateKey
const buffer = Buffer.from(digestHex, 'hex')
const signature = ecsign(buffer, privateKey)
const { r, s, v } = signature
const serializedSignature = {
r: r.toString('hex'),
s: s.toString('hex'),
v,
}
return JSON.stringify(serializedSignature)
}
Example #2
Source File: ethsign.page.ts From Elastos.Essentials.App with MIT License | 6 votes |
async confirmSign(): Promise<void> {
const payPassword = await this.authService.getWalletPassword(this.networkWallet.masterWallet.id, true, true);
if (payPassword === null) { // cancelled by user
await this.cancelOperation();
return;
}
let privateKeyHexNoprefix = await this.walletManager.spvBridge.exportETHSCPrivateKey(jsToSpvWalletId(this.networkWallet.masterWallet.id), this.evmSubWallet.id, payPassword);
let privateKey = Buffer.from(privateKeyHexNoprefix, "hex");
// Implementation taken from Metamask unsafe signing:
// https://github.com/MetaMask/eth-simple-keyring/blob/main/index.js
try {
const message = stripHexPrefix(this.payloadToBeSigned);
const msgSig = ecsign(Buffer.from(message, 'hex'), privateKey);
const rawMsgSig = toRpcSig(msgSig.v, msgSig.r, msgSig.s);
void this.sendIntentResponse({
signedData: rawMsgSig
}, this.receivedIntent.intentId);
}
catch (e) {
// Sign method can throw exception in case some provided content has an invalid format
// i.e.: array value, with "address" type. In such case, we fail silently.
Logger.warn('wallet', 'eth_sign intent error:', e)
await this.sendIntentResponse(
{ data: null },
this.receivedIntent.intentId
);
}
}
Example #3
Source File: bentobox.ts From trident with GNU General Public License v3.0 | 6 votes |
export function getSignedMasterContractApprovalData(
bentoBox: BentoBoxV1,
user: SignerWithAddress,
privateKey: string,
masterContractAddress: string,
approved: boolean,
nonce: BigNumber,
chainId: number
) {
const digest = getBentoBoxApprovalDigest(bentoBox, user, masterContractAddress, approved, nonce, chainId);
const { v, r, s } = ecsign(Buffer.from(digest.slice(2), "hex"), Buffer.from(privateKey.replace("0x", ""), "hex"));
return { v, r, s };
}
Example #4
Source File: index.ts From eip-712 with MIT License | 5 votes |
{ r, s, v } = ecsign(Buffer.from(message), privateKey)
Example #5
Source File: BloomVaultStorageService.ts From affinidi-core-sdk with Apache License 2.0 | 5 votes |
/* istanbul ignore next: ethereumjs-util */
private _signByVaultKeys(message: string, privateKey: string) {
const sig = ecsign(hashPersonalMessage(Buffer.from(message)), Buffer.from(privateKey, 'hex'))
return toRpcSig(sig.v, sig.r, sig.s)
}
Example #6
Source File: signatures.ts From ERC20Permit with GNU General Public License v3.0 | 5 votes |
sign = (digest: any, privateKey: any) => {
return ecsign(Buffer.from(digest.slice(2), 'hex'), privateKey)
}
Example #7
Source File: 123_erc20_permit.ts From fyDai with GNU General Public License v3.0 | 5 votes |
contract('ERC20Permit', async (accounts: string[]) => {
// this is the first account that buidler creates
// https://github.com/nomiclabs/buidler/blob/d399a60452f80a6e88d974b2b9205f4894a60d29/packages/buidler-core/src/internal/core/config/default-config.ts#L41
const ownerPrivateKey = Buffer.from('c5e8f61d1ab959b397eecc0a37a6517b8e67a0e7cf1f4bce5591f3ed80199122', 'hex')
const chainId = 31337 // buidlerevm chain id
let [owner, user] = accounts
let token: Contract
let name: string
beforeEach(async () => {
token = await ERC20.new(1000, { from: owner })
name = await token.name()
})
it('initializes DOMAIN_SEPARATOR and PERMIT_TYPEHASH correctly', async () => {
assert.equal(await token.PERMIT_TYPEHASH(), PERMIT_TYPEHASH)
assert.equal(await token.DOMAIN_SEPARATOR(), getDomainSeparator(name, token.address, chainId))
})
it('permits and emits Approval (replay safe)', async () => {
// Create the approval request
const approve = {
owner: owner,
spender: user,
value: 100,
}
// deadline as much as you want in the future
const deadline = 100000000000000
// Get the user's nonce
const nonce = await token.nonces(owner)
// Get the EIP712 digest
const digest = getPermitDigest(name, token.address, chainId, approve, nonce, deadline)
// Sign it
// NOTE: Using web3.eth.sign will hash the message internally again which
// we do not want, so we're manually signing here
const { v, r, s } = ecsign(Buffer.from(digest.slice(2), 'hex'), ownerPrivateKey)
// Approve it
const receipt = await token.permit(approve.owner, approve.spender, approve.value, deadline, v, r, s)
const event = receipt.logs[0]
// It worked!
assert.equal(event.event, 'Approval')
assert.equal(await token.nonces(owner), 1)
assert.equal(await token.allowance(approve.owner, approve.spender), approve.value)
// Re-using the same sig doesn't work since the nonce has been incremented
// on the contract level for replay-protection
await expectRevert(
token.permit(approve.owner, approve.spender, approve.value, deadline, v, r, s),
'ERC20Permit: invalid signature'
)
// invalid ecrecover's return address(0x0), so we must also guarantee that
// this case fails
await expectRevert(
token.permit(
'0x0000000000000000000000000000000000000000',
approve.spender,
approve.value,
deadline,
'0x99',
r,
s
),
'ERC20Permit: invalid signature'
)
})
})
Example #8
Source File: ApeERC20.spec.ts From apeswap-swap-core with GNU General Public License v3.0 | 4 votes |
describe('ApeERC20', () => {
const provider = new MockProvider(
{
ganacheOptions: {
hardfork: 'istanbul',
mnemonic: 'horn horn horn horn horn horn horn horn horn horn horn horn',
gasLimit: 9999999
}
})
const [wallet, other] = provider.getWallets()
let token: Contract
beforeEach(async () => {
token = await deployContract(wallet, ERC20, [TOTAL_SUPPLY])
})
it('name, symbol, decimals, totalSupply, balanceOf, DOMAIN_SEPARATOR, PERMIT_TYPEHASH', async () => {
const name = await token.name()
expect(name).to.eq('ApeSwapFinance LPs')
expect(await token.symbol()).to.eq('APE-LP')
expect(await token.decimals()).to.eq(18)
expect(await token.totalSupply()).to.eq(TOTAL_SUPPLY)
expect(await token.balanceOf(wallet.address)).to.eq(TOTAL_SUPPLY)
expect(await token.DOMAIN_SEPARATOR()).to.eq(
keccak256(
defaultAbiCoder.encode(
['bytes32', 'bytes32', 'bytes32', 'uint256', 'address'],
[
keccak256(
toUtf8Bytes('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)')
),
keccak256(toUtf8Bytes(name)),
keccak256(toUtf8Bytes('1')),
1,
token.address
]
)
)
)
expect(await token.PERMIT_TYPEHASH()).to.eq(
keccak256(toUtf8Bytes('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)'))
)
})
it('approve', async () => {
await expect(token.approve(other.address, TEST_AMOUNT))
.to.emit(token, 'Approval')
.withArgs(wallet.address, other.address, TEST_AMOUNT)
expect(await token.allowance(wallet.address, other.address)).to.eq(TEST_AMOUNT)
})
it('transfer', async () => {
await expect(token.transfer(other.address, TEST_AMOUNT))
.to.emit(token, 'Transfer')
.withArgs(wallet.address, other.address, TEST_AMOUNT)
expect(await token.balanceOf(wallet.address)).to.eq(TOTAL_SUPPLY.sub(TEST_AMOUNT))
expect(await token.balanceOf(other.address)).to.eq(TEST_AMOUNT)
})
it('transfer:fail', async () => {
await expect(token.transfer(other.address, TOTAL_SUPPLY.add(1))).to.be.reverted // ds-math-sub-underflow
await expect(token.connect(other).transfer(wallet.address, 1)).to.be.reverted // ds-math-sub-underflow
})
it('transferFrom', async () => {
await token.approve(other.address, TEST_AMOUNT)
await expect(token.connect(other).transferFrom(wallet.address, other.address, TEST_AMOUNT))
.to.emit(token, 'Transfer')
.withArgs(wallet.address, other.address, TEST_AMOUNT)
expect(await token.allowance(wallet.address, other.address)).to.eq(0)
expect(await token.balanceOf(wallet.address)).to.eq(TOTAL_SUPPLY.sub(TEST_AMOUNT))
expect(await token.balanceOf(other.address)).to.eq(TEST_AMOUNT)
})
it('transferFrom:max', async () => {
await token.approve(other.address, MaxUint256)
await expect(token.connect(other).transferFrom(wallet.address, other.address, TEST_AMOUNT))
.to.emit(token, 'Transfer')
.withArgs(wallet.address, other.address, TEST_AMOUNT)
expect(await token.allowance(wallet.address, other.address)).to.eq(MaxUint256)
expect(await token.balanceOf(wallet.address)).to.eq(TOTAL_SUPPLY.sub(TEST_AMOUNT))
expect(await token.balanceOf(other.address)).to.eq(TEST_AMOUNT)
})
it('permit', async () => {
const nonce = await token.nonces(wallet.address)
const deadline = MaxUint256
const digest = await getApprovalDigest(
token,
{ owner: wallet.address, spender: other.address, value: TEST_AMOUNT },
nonce,
deadline
)
const { v, r, s } = ecsign(Buffer.from(digest.slice(2), 'hex'), Buffer.from(wallet.privateKey.slice(2), 'hex'))
await expect(token.permit(wallet.address, other.address, TEST_AMOUNT, deadline, v, hexlify(r), hexlify(s)))
.to.emit(token, 'Approval')
.withArgs(wallet.address, other.address, TEST_AMOUNT)
expect(await token.allowance(wallet.address, other.address)).to.eq(TEST_AMOUNT)
expect(await token.nonces(wallet.address)).to.eq(BigNumber.from(1))
})
})
Example #9
Source File: PancakeERC20.spec.ts From pancake-swap-testnet with MIT License | 4 votes |
describe('PancakeERC20', () => {
const provider = new MockProvider({
hardfork: 'istanbul',
mnemonic: 'horn horn horn horn horn horn horn horn horn horn horn horn',
gasLimit: 9999999
})
const [wallet, other] = provider.getWallets()
let token: Contract
beforeEach(async () => {
token = await deployContract(wallet, ERC20, [TOTAL_SUPPLY])
})
it('name, symbol, decimals, totalSupply, balanceOf, DOMAIN_SEPARATOR, PERMIT_TYPEHASH', async () => {
const name = await token.name()
expect(name).to.eq('Pancake LPs')
expect(await token.symbol()).to.eq('Cake-LP')
expect(await token.decimals()).to.eq(18)
expect(await token.totalSupply()).to.eq(TOTAL_SUPPLY)
expect(await token.balanceOf(wallet.address)).to.eq(TOTAL_SUPPLY)
expect(await token.DOMAIN_SEPARATOR()).to.eq(
keccak256(
defaultAbiCoder.encode(
['bytes32', 'bytes32', 'bytes32', 'uint256', 'address'],
[
keccak256(
toUtf8Bytes('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)')
),
keccak256(toUtf8Bytes(name)),
keccak256(toUtf8Bytes('1')),
1,
token.address
]
)
)
)
expect(await token.PERMIT_TYPEHASH()).to.eq(
keccak256(toUtf8Bytes('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)'))
)
})
it('approve', async () => {
await expect(token.approve(other.address, TEST_AMOUNT))
.to.emit(token, 'Approval')
.withArgs(wallet.address, other.address, TEST_AMOUNT)
expect(await token.allowance(wallet.address, other.address)).to.eq(TEST_AMOUNT)
})
it('transfer', async () => {
await expect(token.transfer(other.address, TEST_AMOUNT))
.to.emit(token, 'Transfer')
.withArgs(wallet.address, other.address, TEST_AMOUNT)
expect(await token.balanceOf(wallet.address)).to.eq(TOTAL_SUPPLY.sub(TEST_AMOUNT))
expect(await token.balanceOf(other.address)).to.eq(TEST_AMOUNT)
})
it('transfer:fail', async () => {
await expect(token.transfer(other.address, TOTAL_SUPPLY.add(1))).to.be.reverted // ds-math-sub-underflow
await expect(token.connect(other).transfer(wallet.address, 1)).to.be.reverted // ds-math-sub-underflow
})
it('transferFrom', async () => {
await token.approve(other.address, TEST_AMOUNT)
await expect(token.connect(other).transferFrom(wallet.address, other.address, TEST_AMOUNT))
.to.emit(token, 'Transfer')
.withArgs(wallet.address, other.address, TEST_AMOUNT)
expect(await token.allowance(wallet.address, other.address)).to.eq(0)
expect(await token.balanceOf(wallet.address)).to.eq(TOTAL_SUPPLY.sub(TEST_AMOUNT))
expect(await token.balanceOf(other.address)).to.eq(TEST_AMOUNT)
})
it('transferFrom:max', async () => {
await token.approve(other.address, MaxUint256)
await expect(token.connect(other).transferFrom(wallet.address, other.address, TEST_AMOUNT))
.to.emit(token, 'Transfer')
.withArgs(wallet.address, other.address, TEST_AMOUNT)
expect(await token.allowance(wallet.address, other.address)).to.eq(MaxUint256)
expect(await token.balanceOf(wallet.address)).to.eq(TOTAL_SUPPLY.sub(TEST_AMOUNT))
expect(await token.balanceOf(other.address)).to.eq(TEST_AMOUNT)
})
it('permit', async () => {
const nonce = await token.nonces(wallet.address)
const deadline = MaxUint256
const digest = await getApprovalDigest(
token,
{ owner: wallet.address, spender: other.address, value: TEST_AMOUNT },
nonce,
deadline
)
const { v, r, s } = ecsign(Buffer.from(digest.slice(2), 'hex'), Buffer.from(wallet.privateKey.slice(2), 'hex'))
await expect(token.permit(wallet.address, other.address, TEST_AMOUNT, deadline, v, hexlify(r), hexlify(s)))
.to.emit(token, 'Approval')
.withArgs(wallet.address, other.address, TEST_AMOUNT)
expect(await token.allowance(wallet.address, other.address)).to.eq(TEST_AMOUNT)
expect(await token.nonces(wallet.address)).to.eq(bigNumberify(1))
})
})
Example #10
Source File: UniswapV2Router01.spec.ts From pancake-swap-testnet with MIT License | 4 votes |
describe('UniswapV2Router{01,02}', () => {
for (const routerVersion of Object.keys(RouterVersion)) {
const provider = new MockProvider({
hardfork: 'istanbul',
mnemonic: 'horn horn horn horn horn horn horn horn horn horn horn horn',
gasLimit: 9999999
})
const [wallet] = provider.getWallets()
const loadFixture = createFixtureLoader(provider, [wallet])
let token0: Contract
let token1: Contract
let WETH: Contract
let WETHPartner: Contract
let factory: Contract
let router: Contract
let pair: Contract
let WETHPair: Contract
let routerEventEmitter: Contract
beforeEach(async function() {
const fixture = await loadFixture(v2Fixture)
token0 = fixture.token0
token1 = fixture.token1
WETH = fixture.WETH
WETHPartner = fixture.WETHPartner
factory = fixture.factoryV2
router = {
[RouterVersion.UniswapV2Router01]: fixture.router01,
[RouterVersion.UniswapV2Router02]: fixture.router02
}[routerVersion as RouterVersion]
pair = fixture.pair
WETHPair = fixture.WETHPair
routerEventEmitter = fixture.routerEventEmitter
})
afterEach(async function() {
expect(await provider.getBalance(router.address)).to.eq(Zero)
})
describe(routerVersion, () => {
it('factory, WETH', async () => {
expect(await router.factory()).to.eq(factory.address)
expect(await router.WETH()).to.eq(WETH.address)
})
it('addLiquidity', async () => {
const token0Amount = expandTo18Decimals(1)
const token1Amount = expandTo18Decimals(4)
const expectedLiquidity = expandTo18Decimals(2)
await token0.approve(router.address, MaxUint256)
await token1.approve(router.address, MaxUint256)
await expect(
router.addLiquidity(
token0.address,
token1.address,
token0Amount,
token1Amount,
0,
0,
wallet.address,
MaxUint256,
overrides
)
)
.to.emit(token0, 'Transfer')
.withArgs(wallet.address, pair.address, token0Amount)
.to.emit(token1, 'Transfer')
.withArgs(wallet.address, pair.address, token1Amount)
.to.emit(pair, 'Transfer')
.withArgs(AddressZero, AddressZero, MINIMUM_LIQUIDITY)
.to.emit(pair, 'Transfer')
.withArgs(AddressZero, wallet.address, expectedLiquidity.sub(MINIMUM_LIQUIDITY))
.to.emit(pair, 'Sync')
.withArgs(token0Amount, token1Amount)
.to.emit(pair, 'Mint')
.withArgs(router.address, token0Amount, token1Amount)
expect(await pair.balanceOf(wallet.address)).to.eq(expectedLiquidity.sub(MINIMUM_LIQUIDITY))
})
it('addLiquidityETH', async () => {
const WETHPartnerAmount = expandTo18Decimals(1)
const ETHAmount = expandTo18Decimals(4)
const expectedLiquidity = expandTo18Decimals(2)
const WETHPairToken0 = await WETHPair.token0()
await WETHPartner.approve(router.address, MaxUint256)
await expect(
router.addLiquidityETH(
WETHPartner.address,
WETHPartnerAmount,
WETHPartnerAmount,
ETHAmount,
wallet.address,
MaxUint256,
{ ...overrides, value: ETHAmount }
)
)
.to.emit(WETHPair, 'Transfer')
.withArgs(AddressZero, AddressZero, MINIMUM_LIQUIDITY)
.to.emit(WETHPair, 'Transfer')
.withArgs(AddressZero, wallet.address, expectedLiquidity.sub(MINIMUM_LIQUIDITY))
.to.emit(WETHPair, 'Sync')
.withArgs(
WETHPairToken0 === WETHPartner.address ? WETHPartnerAmount : ETHAmount,
WETHPairToken0 === WETHPartner.address ? ETHAmount : WETHPartnerAmount
)
.to.emit(WETHPair, 'Mint')
.withArgs(
router.address,
WETHPairToken0 === WETHPartner.address ? WETHPartnerAmount : ETHAmount,
WETHPairToken0 === WETHPartner.address ? ETHAmount : WETHPartnerAmount
)
expect(await WETHPair.balanceOf(wallet.address)).to.eq(expectedLiquidity.sub(MINIMUM_LIQUIDITY))
})
async function addLiquidity(token0Amount: BigNumber, token1Amount: BigNumber) {
await token0.transfer(pair.address, token0Amount)
await token1.transfer(pair.address, token1Amount)
await pair.mint(wallet.address, overrides)
}
it('removeLiquidity', async () => {
const token0Amount = expandTo18Decimals(1)
const token1Amount = expandTo18Decimals(4)
await addLiquidity(token0Amount, token1Amount)
const expectedLiquidity = expandTo18Decimals(2)
await pair.approve(router.address, MaxUint256)
await expect(
router.removeLiquidity(
token0.address,
token1.address,
expectedLiquidity.sub(MINIMUM_LIQUIDITY),
0,
0,
wallet.address,
MaxUint256,
overrides
)
)
.to.emit(pair, 'Transfer')
.withArgs(wallet.address, pair.address, expectedLiquidity.sub(MINIMUM_LIQUIDITY))
.to.emit(pair, 'Transfer')
.withArgs(pair.address, AddressZero, expectedLiquidity.sub(MINIMUM_LIQUIDITY))
.to.emit(token0, 'Transfer')
.withArgs(pair.address, wallet.address, token0Amount.sub(500))
.to.emit(token1, 'Transfer')
.withArgs(pair.address, wallet.address, token1Amount.sub(2000))
.to.emit(pair, 'Sync')
.withArgs(500, 2000)
.to.emit(pair, 'Burn')
.withArgs(router.address, token0Amount.sub(500), token1Amount.sub(2000), wallet.address)
expect(await pair.balanceOf(wallet.address)).to.eq(0)
const totalSupplyToken0 = await token0.totalSupply()
const totalSupplyToken1 = await token1.totalSupply()
expect(await token0.balanceOf(wallet.address)).to.eq(totalSupplyToken0.sub(500))
expect(await token1.balanceOf(wallet.address)).to.eq(totalSupplyToken1.sub(2000))
})
it('removeLiquidityETH', async () => {
const WETHPartnerAmount = expandTo18Decimals(1)
const ETHAmount = expandTo18Decimals(4)
await WETHPartner.transfer(WETHPair.address, WETHPartnerAmount)
await WETH.deposit({ value: ETHAmount })
await WETH.transfer(WETHPair.address, ETHAmount)
await WETHPair.mint(wallet.address, overrides)
const expectedLiquidity = expandTo18Decimals(2)
const WETHPairToken0 = await WETHPair.token0()
await WETHPair.approve(router.address, MaxUint256)
await expect(
router.removeLiquidityETH(
WETHPartner.address,
expectedLiquidity.sub(MINIMUM_LIQUIDITY),
0,
0,
wallet.address,
MaxUint256,
overrides
)
)
.to.emit(WETHPair, 'Transfer')
.withArgs(wallet.address, WETHPair.address, expectedLiquidity.sub(MINIMUM_LIQUIDITY))
.to.emit(WETHPair, 'Transfer')
.withArgs(WETHPair.address, AddressZero, expectedLiquidity.sub(MINIMUM_LIQUIDITY))
.to.emit(WETH, 'Transfer')
.withArgs(WETHPair.address, router.address, ETHAmount.sub(2000))
.to.emit(WETHPartner, 'Transfer')
.withArgs(WETHPair.address, router.address, WETHPartnerAmount.sub(500))
.to.emit(WETHPartner, 'Transfer')
.withArgs(router.address, wallet.address, WETHPartnerAmount.sub(500))
.to.emit(WETHPair, 'Sync')
.withArgs(
WETHPairToken0 === WETHPartner.address ? 500 : 2000,
WETHPairToken0 === WETHPartner.address ? 2000 : 500
)
.to.emit(WETHPair, 'Burn')
.withArgs(
router.address,
WETHPairToken0 === WETHPartner.address ? WETHPartnerAmount.sub(500) : ETHAmount.sub(2000),
WETHPairToken0 === WETHPartner.address ? ETHAmount.sub(2000) : WETHPartnerAmount.sub(500),
router.address
)
expect(await WETHPair.balanceOf(wallet.address)).to.eq(0)
const totalSupplyWETHPartner = await WETHPartner.totalSupply()
const totalSupplyWETH = await WETH.totalSupply()
expect(await WETHPartner.balanceOf(wallet.address)).to.eq(totalSupplyWETHPartner.sub(500))
expect(await WETH.balanceOf(wallet.address)).to.eq(totalSupplyWETH.sub(2000))
})
it('removeLiquidityWithPermit', async () => {
const token0Amount = expandTo18Decimals(1)
const token1Amount = expandTo18Decimals(4)
await addLiquidity(token0Amount, token1Amount)
const expectedLiquidity = expandTo18Decimals(2)
const nonce = await pair.nonces(wallet.address)
const digest = await getApprovalDigest(
pair,
{ owner: wallet.address, spender: router.address, value: expectedLiquidity.sub(MINIMUM_LIQUIDITY) },
nonce,
MaxUint256
)
const { v, r, s } = ecsign(Buffer.from(digest.slice(2), 'hex'), Buffer.from(wallet.privateKey.slice(2), 'hex'))
await router.removeLiquidityWithPermit(
token0.address,
token1.address,
expectedLiquidity.sub(MINIMUM_LIQUIDITY),
0,
0,
wallet.address,
MaxUint256,
false,
v,
r,
s,
overrides
)
})
it('removeLiquidityETHWithPermit', async () => {
const WETHPartnerAmount = expandTo18Decimals(1)
const ETHAmount = expandTo18Decimals(4)
await WETHPartner.transfer(WETHPair.address, WETHPartnerAmount)
await WETH.deposit({ value: ETHAmount })
await WETH.transfer(WETHPair.address, ETHAmount)
await WETHPair.mint(wallet.address, overrides)
const expectedLiquidity = expandTo18Decimals(2)
const nonce = await WETHPair.nonces(wallet.address)
const digest = await getApprovalDigest(
WETHPair,
{ owner: wallet.address, spender: router.address, value: expectedLiquidity.sub(MINIMUM_LIQUIDITY) },
nonce,
MaxUint256
)
const { v, r, s } = ecsign(Buffer.from(digest.slice(2), 'hex'), Buffer.from(wallet.privateKey.slice(2), 'hex'))
await router.removeLiquidityETHWithPermit(
WETHPartner.address,
expectedLiquidity.sub(MINIMUM_LIQUIDITY),
0,
0,
wallet.address,
MaxUint256,
false,
v,
r,
s,
overrides
)
})
describe('swapExactTokensForTokens', () => {
const token0Amount = expandTo18Decimals(5)
const token1Amount = expandTo18Decimals(10)
const swapAmount = expandTo18Decimals(1)
const expectedOutputAmount = bigNumberify('1662497915624478906')
beforeEach(async () => {
await addLiquidity(token0Amount, token1Amount)
await token0.approve(router.address, MaxUint256)
})
it('happy path', async () => {
await expect(
router.swapExactTokensForTokens(
swapAmount,
0,
[token0.address, token1.address],
wallet.address,
MaxUint256,
overrides
)
)
.to.emit(token0, 'Transfer')
.withArgs(wallet.address, pair.address, swapAmount)
.to.emit(token1, 'Transfer')
.withArgs(pair.address, wallet.address, expectedOutputAmount)
.to.emit(pair, 'Sync')
.withArgs(token0Amount.add(swapAmount), token1Amount.sub(expectedOutputAmount))
.to.emit(pair, 'Swap')
.withArgs(router.address, swapAmount, 0, 0, expectedOutputAmount, wallet.address)
})
it('amounts', async () => {
await token0.approve(routerEventEmitter.address, MaxUint256)
await expect(
routerEventEmitter.swapExactTokensForTokens(
router.address,
swapAmount,
0,
[token0.address, token1.address],
wallet.address,
MaxUint256,
overrides
)
)
.to.emit(routerEventEmitter, 'Amounts')
.withArgs([swapAmount, expectedOutputAmount])
})
it('gas', async () => {
// ensure that setting price{0,1}CumulativeLast for the first time doesn't affect our gas math
await mineBlock(provider, (await provider.getBlock('latest')).timestamp + 1)
await pair.sync(overrides)
await token0.approve(router.address, MaxUint256)
await mineBlock(provider, (await provider.getBlock('latest')).timestamp + 1)
const tx = await router.swapExactTokensForTokens(
swapAmount,
0,
[token0.address, token1.address],
wallet.address,
MaxUint256,
overrides
)
const receipt = await tx.wait()
expect(receipt.gasUsed).to.eq(
{
[RouterVersion.UniswapV2Router01]: 101876,
[RouterVersion.UniswapV2Router02]: 101898
}[routerVersion as RouterVersion]
)
}).retries(3)
})
describe('swapTokensForExactTokens', () => {
const token0Amount = expandTo18Decimals(5)
const token1Amount = expandTo18Decimals(10)
const expectedSwapAmount = bigNumberify('557227237267357629')
const outputAmount = expandTo18Decimals(1)
beforeEach(async () => {
await addLiquidity(token0Amount, token1Amount)
})
it('happy path', async () => {
await token0.approve(router.address, MaxUint256)
await expect(
router.swapTokensForExactTokens(
outputAmount,
MaxUint256,
[token0.address, token1.address],
wallet.address,
MaxUint256,
overrides
)
)
.to.emit(token0, 'Transfer')
.withArgs(wallet.address, pair.address, expectedSwapAmount)
.to.emit(token1, 'Transfer')
.withArgs(pair.address, wallet.address, outputAmount)
.to.emit(pair, 'Sync')
.withArgs(token0Amount.add(expectedSwapAmount), token1Amount.sub(outputAmount))
.to.emit(pair, 'Swap')
.withArgs(router.address, expectedSwapAmount, 0, 0, outputAmount, wallet.address)
})
it('amounts', async () => {
await token0.approve(routerEventEmitter.address, MaxUint256)
await expect(
routerEventEmitter.swapTokensForExactTokens(
router.address,
outputAmount,
MaxUint256,
[token0.address, token1.address],
wallet.address,
MaxUint256,
overrides
)
)
.to.emit(routerEventEmitter, 'Amounts')
.withArgs([expectedSwapAmount, outputAmount])
})
})
describe('swapExactETHForTokens', () => {
const WETHPartnerAmount = expandTo18Decimals(10)
const ETHAmount = expandTo18Decimals(5)
const swapAmount = expandTo18Decimals(1)
const expectedOutputAmount = bigNumberify('1662497915624478906')
beforeEach(async () => {
await WETHPartner.transfer(WETHPair.address, WETHPartnerAmount)
await WETH.deposit({ value: ETHAmount })
await WETH.transfer(WETHPair.address, ETHAmount)
await WETHPair.mint(wallet.address, overrides)
await token0.approve(router.address, MaxUint256)
})
it('happy path', async () => {
const WETHPairToken0 = await WETHPair.token0()
await expect(
router.swapExactETHForTokens(0, [WETH.address, WETHPartner.address], wallet.address, MaxUint256, {
...overrides,
value: swapAmount
})
)
.to.emit(WETH, 'Transfer')
.withArgs(router.address, WETHPair.address, swapAmount)
.to.emit(WETHPartner, 'Transfer')
.withArgs(WETHPair.address, wallet.address, expectedOutputAmount)
.to.emit(WETHPair, 'Sync')
.withArgs(
WETHPairToken0 === WETHPartner.address
? WETHPartnerAmount.sub(expectedOutputAmount)
: ETHAmount.add(swapAmount),
WETHPairToken0 === WETHPartner.address
? ETHAmount.add(swapAmount)
: WETHPartnerAmount.sub(expectedOutputAmount)
)
.to.emit(WETHPair, 'Swap')
.withArgs(
router.address,
WETHPairToken0 === WETHPartner.address ? 0 : swapAmount,
WETHPairToken0 === WETHPartner.address ? swapAmount : 0,
WETHPairToken0 === WETHPartner.address ? expectedOutputAmount : 0,
WETHPairToken0 === WETHPartner.address ? 0 : expectedOutputAmount,
wallet.address
)
})
it('amounts', async () => {
await expect(
routerEventEmitter.swapExactETHForTokens(
router.address,
0,
[WETH.address, WETHPartner.address],
wallet.address,
MaxUint256,
{
...overrides,
value: swapAmount
}
)
)
.to.emit(routerEventEmitter, 'Amounts')
.withArgs([swapAmount, expectedOutputAmount])
})
it('gas', async () => {
const WETHPartnerAmount = expandTo18Decimals(10)
const ETHAmount = expandTo18Decimals(5)
await WETHPartner.transfer(WETHPair.address, WETHPartnerAmount)
await WETH.deposit({ value: ETHAmount })
await WETH.transfer(WETHPair.address, ETHAmount)
await WETHPair.mint(wallet.address, overrides)
// ensure that setting price{0,1}CumulativeLast for the first time doesn't affect our gas math
await mineBlock(provider, (await provider.getBlock('latest')).timestamp + 1)
await pair.sync(overrides)
const swapAmount = expandTo18Decimals(1)
await mineBlock(provider, (await provider.getBlock('latest')).timestamp + 1)
const tx = await router.swapExactETHForTokens(
0,
[WETH.address, WETHPartner.address],
wallet.address,
MaxUint256,
{
...overrides,
value: swapAmount
}
)
const receipt = await tx.wait()
expect(receipt.gasUsed).to.eq(
{
[RouterVersion.UniswapV2Router01]: 138770,
[RouterVersion.UniswapV2Router02]: 138770
}[routerVersion as RouterVersion]
)
}).retries(3)
})
describe('swapTokensForExactETH', () => {
const WETHPartnerAmount = expandTo18Decimals(5)
const ETHAmount = expandTo18Decimals(10)
const expectedSwapAmount = bigNumberify('557227237267357629')
const outputAmount = expandTo18Decimals(1)
beforeEach(async () => {
await WETHPartner.transfer(WETHPair.address, WETHPartnerAmount)
await WETH.deposit({ value: ETHAmount })
await WETH.transfer(WETHPair.address, ETHAmount)
await WETHPair.mint(wallet.address, overrides)
})
it('happy path', async () => {
await WETHPartner.approve(router.address, MaxUint256)
const WETHPairToken0 = await WETHPair.token0()
await expect(
router.swapTokensForExactETH(
outputAmount,
MaxUint256,
[WETHPartner.address, WETH.address],
wallet.address,
MaxUint256,
overrides
)
)
.to.emit(WETHPartner, 'Transfer')
.withArgs(wallet.address, WETHPair.address, expectedSwapAmount)
.to.emit(WETH, 'Transfer')
.withArgs(WETHPair.address, router.address, outputAmount)
.to.emit(WETHPair, 'Sync')
.withArgs(
WETHPairToken0 === WETHPartner.address
? WETHPartnerAmount.add(expectedSwapAmount)
: ETHAmount.sub(outputAmount),
WETHPairToken0 === WETHPartner.address
? ETHAmount.sub(outputAmount)
: WETHPartnerAmount.add(expectedSwapAmount)
)
.to.emit(WETHPair, 'Swap')
.withArgs(
router.address,
WETHPairToken0 === WETHPartner.address ? expectedSwapAmount : 0,
WETHPairToken0 === WETHPartner.address ? 0 : expectedSwapAmount,
WETHPairToken0 === WETHPartner.address ? 0 : outputAmount,
WETHPairToken0 === WETHPartner.address ? outputAmount : 0,
router.address
)
})
it('amounts', async () => {
await WETHPartner.approve(routerEventEmitter.address, MaxUint256)
await expect(
routerEventEmitter.swapTokensForExactETH(
router.address,
outputAmount,
MaxUint256,
[WETHPartner.address, WETH.address],
wallet.address,
MaxUint256,
overrides
)
)
.to.emit(routerEventEmitter, 'Amounts')
.withArgs([expectedSwapAmount, outputAmount])
})
})
describe('swapExactTokensForETH', () => {
const WETHPartnerAmount = expandTo18Decimals(5)
const ETHAmount = expandTo18Decimals(10)
const swapAmount = expandTo18Decimals(1)
const expectedOutputAmount = bigNumberify('1662497915624478906')
beforeEach(async () => {
await WETHPartner.transfer(WETHPair.address, WETHPartnerAmount)
await WETH.deposit({ value: ETHAmount })
await WETH.transfer(WETHPair.address, ETHAmount)
await WETHPair.mint(wallet.address, overrides)
})
it('happy path', async () => {
await WETHPartner.approve(router.address, MaxUint256)
const WETHPairToken0 = await WETHPair.token0()
await expect(
router.swapExactTokensForETH(
swapAmount,
0,
[WETHPartner.address, WETH.address],
wallet.address,
MaxUint256,
overrides
)
)
.to.emit(WETHPartner, 'Transfer')
.withArgs(wallet.address, WETHPair.address, swapAmount)
.to.emit(WETH, 'Transfer')
.withArgs(WETHPair.address, router.address, expectedOutputAmount)
.to.emit(WETHPair, 'Sync')
.withArgs(
WETHPairToken0 === WETHPartner.address
? WETHPartnerAmount.add(swapAmount)
: ETHAmount.sub(expectedOutputAmount),
WETHPairToken0 === WETHPartner.address
? ETHAmount.sub(expectedOutputAmount)
: WETHPartnerAmount.add(swapAmount)
)
.to.emit(WETHPair, 'Swap')
.withArgs(
router.address,
WETHPairToken0 === WETHPartner.address ? swapAmount : 0,
WETHPairToken0 === WETHPartner.address ? 0 : swapAmount,
WETHPairToken0 === WETHPartner.address ? 0 : expectedOutputAmount,
WETHPairToken0 === WETHPartner.address ? expectedOutputAmount : 0,
router.address
)
})
it('amounts', async () => {
await WETHPartner.approve(routerEventEmitter.address, MaxUint256)
await expect(
routerEventEmitter.swapExactTokensForETH(
router.address,
swapAmount,
0,
[WETHPartner.address, WETH.address],
wallet.address,
MaxUint256,
overrides
)
)
.to.emit(routerEventEmitter, 'Amounts')
.withArgs([swapAmount, expectedOutputAmount])
})
})
describe('swapETHForExactTokens', () => {
const WETHPartnerAmount = expandTo18Decimals(10)
const ETHAmount = expandTo18Decimals(5)
const expectedSwapAmount = bigNumberify('557227237267357629')
const outputAmount = expandTo18Decimals(1)
beforeEach(async () => {
await WETHPartner.transfer(WETHPair.address, WETHPartnerAmount)
await WETH.deposit({ value: ETHAmount })
await WETH.transfer(WETHPair.address, ETHAmount)
await WETHPair.mint(wallet.address, overrides)
})
it('happy path', async () => {
const WETHPairToken0 = await WETHPair.token0()
await expect(
router.swapETHForExactTokens(
outputAmount,
[WETH.address, WETHPartner.address],
wallet.address,
MaxUint256,
{
...overrides,
value: expectedSwapAmount
}
)
)
.to.emit(WETH, 'Transfer')
.withArgs(router.address, WETHPair.address, expectedSwapAmount)
.to.emit(WETHPartner, 'Transfer')
.withArgs(WETHPair.address, wallet.address, outputAmount)
.to.emit(WETHPair, 'Sync')
.withArgs(
WETHPairToken0 === WETHPartner.address
? WETHPartnerAmount.sub(outputAmount)
: ETHAmount.add(expectedSwapAmount),
WETHPairToken0 === WETHPartner.address
? ETHAmount.add(expectedSwapAmount)
: WETHPartnerAmount.sub(outputAmount)
)
.to.emit(WETHPair, 'Swap')
.withArgs(
router.address,
WETHPairToken0 === WETHPartner.address ? 0 : expectedSwapAmount,
WETHPairToken0 === WETHPartner.address ? expectedSwapAmount : 0,
WETHPairToken0 === WETHPartner.address ? outputAmount : 0,
WETHPairToken0 === WETHPartner.address ? 0 : outputAmount,
wallet.address
)
})
it('amounts', async () => {
await expect(
routerEventEmitter.swapETHForExactTokens(
router.address,
outputAmount,
[WETH.address, WETHPartner.address],
wallet.address,
MaxUint256,
{
...overrides,
value: expectedSwapAmount
}
)
)
.to.emit(routerEventEmitter, 'Amounts')
.withArgs([expectedSwapAmount, outputAmount])
})
})
})
}
})
Example #11
Source File: StakingRewards.spec.ts From staking-factory with MIT License | 4 votes |
describe('StakingRewards', () => {
const provider = new MockProvider({
ganacheOptions: {
hardfork: 'istanbul',
mnemonic: 'horn horn horn horn horn horn horn horn horn horn horn horn',
gasLimit: 9999999,
},
})
const [wallet, staker, secondStaker] = provider.getWallets()
const loadFixture = createFixtureLoader([wallet], provider)
let stakingRewards: Contract
let rewardsToken: Contract
let stakingToken: Contract
beforeEach(async () => {
const fixture = await loadFixture(stakingRewardsFixture)
stakingRewards = fixture.stakingRewards
rewardsToken = fixture.rewardsToken
stakingToken = fixture.stakingToken
})
it('deploy cost', async () => {
const stakingRewards = await deployContract(wallet, StakingRewards, [
wallet.address,
rewardsToken.address,
stakingToken.address,
])
const receipt = await provider.getTransactionReceipt(stakingRewards.deployTransaction.hash)
expect(receipt.gasUsed).to.eq('1418436')
})
it('rewardsDuration', async () => {
const rewardsDuration = await stakingRewards.rewardsDuration()
expect(rewardsDuration).to.be.eq(REWARDS_DURATION)
})
const reward = expandTo18Decimals(100)
async function start(reward: BigNumber): Promise<{ startTime: BigNumber; endTime: BigNumber }> {
// send reward to the contract
await rewardsToken.transfer(stakingRewards.address, reward)
// must be called by rewardsDistribution
await stakingRewards.notifyRewardAmount(reward)
const startTime: BigNumber = await stakingRewards.lastUpdateTime()
const endTime: BigNumber = await stakingRewards.periodFinish()
expect(endTime).to.be.eq(startTime.add(REWARDS_DURATION))
return { startTime, endTime }
}
it('notifyRewardAmount: full', async () => {
// stake with staker
const stake = expandTo18Decimals(2)
await stakingToken.transfer(staker.address, stake)
await stakingToken.connect(staker).approve(stakingRewards.address, stake)
await stakingRewards.connect(staker).stake(stake)
const { endTime } = await start(reward)
// fast-forward past the reward window
await mineBlock(provider, endTime.add(1).toNumber())
// unstake
await stakingRewards.connect(staker).exit()
const stakeEndTime: BigNumber = await stakingRewards.lastUpdateTime()
expect(stakeEndTime).to.be.eq(endTime)
const rewardAmount = await rewardsToken.balanceOf(staker.address)
expect(reward.sub(rewardAmount).lte(reward.div(10000))).to.be.true // ensure result is within .01%
expect(rewardAmount).to.be.eq(reward.div(REWARDS_DURATION).mul(REWARDS_DURATION))
})
it('stakeWithPermit', async () => {
// stake with staker
const stake = expandTo18Decimals(2)
await stakingToken.transfer(staker.address, stake)
// get permit
const nonce = await stakingToken.nonces(staker.address)
const deadline = constants.MaxUint256
const digest = await getApprovalDigest(
stakingToken,
{ owner: staker.address, spender: stakingRewards.address, value: stake },
nonce,
deadline
)
const { v, r, s } = ecsign(Buffer.from(digest.slice(2), 'hex'), Buffer.from(staker.privateKey.slice(2), 'hex'))
await stakingRewards.connect(staker).stakeWithPermit(stake, deadline, v, r, s)
const { endTime } = await start(reward)
// fast-forward past the reward window
await mineBlock(provider, endTime.add(1).toNumber())
// unstake
await stakingRewards.connect(staker).exit()
const stakeEndTime: BigNumber = await stakingRewards.lastUpdateTime()
expect(stakeEndTime).to.be.eq(endTime)
const rewardAmount = await rewardsToken.balanceOf(staker.address)
expect(reward.sub(rewardAmount).lte(reward.div(10000))).to.be.true // ensure result is within .01%
expect(rewardAmount).to.be.eq(reward.div(REWARDS_DURATION).mul(REWARDS_DURATION))
})
it('notifyRewardAmount: ~half', async () => {
const { startTime, endTime } = await start(reward)
// fast-forward ~halfway through the reward window
await mineBlock(provider, startTime.add(endTime.sub(startTime).div(2)).toNumber())
// stake with staker
const stake = expandTo18Decimals(2)
await stakingToken.transfer(staker.address, stake)
await stakingToken.connect(staker).approve(stakingRewards.address, stake)
await stakingRewards.connect(staker).stake(stake)
const stakeStartTime: BigNumber = await stakingRewards.lastUpdateTime()
// fast-forward past the reward window
await mineBlock(provider, endTime.add(1).toNumber())
// unstake
await stakingRewards.connect(staker).exit()
const stakeEndTime: BigNumber = await stakingRewards.lastUpdateTime()
expect(stakeEndTime).to.be.eq(endTime)
const rewardAmount = await rewardsToken.balanceOf(staker.address)
expect(reward.div(2).sub(rewardAmount).lte(reward.div(2).div(10000))).to.be.true // ensure result is within .01%
expect(rewardAmount).to.be.eq(reward.div(REWARDS_DURATION).mul(endTime.sub(stakeStartTime)))
}).retries(2)
it('notifyRewardAmount: two stakers', async () => {
// stake with first staker
const stake = expandTo18Decimals(2)
await stakingToken.transfer(staker.address, stake)
await stakingToken.connect(staker).approve(stakingRewards.address, stake)
await stakingRewards.connect(staker).stake(stake)
const { startTime, endTime } = await start(reward)
// fast-forward ~halfway through the reward window
await mineBlock(provider, startTime.add(endTime.sub(startTime).div(2)).toNumber())
// stake with second staker
await stakingToken.transfer(secondStaker.address, stake)
await stakingToken.connect(secondStaker).approve(stakingRewards.address, stake)
await stakingRewards.connect(secondStaker).stake(stake)
// fast-forward past the reward window
await mineBlock(provider, endTime.add(1).toNumber())
// unstake
await stakingRewards.connect(staker).exit()
const stakeEndTime: BigNumber = await stakingRewards.lastUpdateTime()
expect(stakeEndTime).to.be.eq(endTime)
await stakingRewards.connect(secondStaker).exit()
const rewardAmount = await rewardsToken.balanceOf(staker.address)
const secondRewardAmount = await rewardsToken.balanceOf(secondStaker.address)
const totalReward = rewardAmount.add(secondRewardAmount)
// ensure results are within .01%
expect(reward.sub(totalReward).lte(reward.div(10000))).to.be.true
expect(totalReward.mul(3).div(4).sub(rewardAmount).lte(totalReward.mul(3).div(4).div(10000)))
expect(totalReward.div(4).sub(secondRewardAmount).lte(totalReward.div(4).div(10000)))
})
})
Example #12
Source File: VvsERC20.spec.ts From vvs-swap-core with GNU General Public License v3.0 | 4 votes |
describe("VVSERC20", () => {
const provider = new MockProvider({
ganacheOptions: {
hardfork: "istanbul",
mnemonic: "horn horn horn horn horn horn horn horn horn horn horn horn",
gasLimit: 9999999
}
});
const [wallet, other] = provider.getWallets();
let token: Contract;
beforeEach(async () => {
token = await deployContract(wallet, ERC20, [TOTAL_SUPPLY]);
});
it("name, symbol, decimals, totalSupply, balanceOf, DOMAIN_SEPARATOR, PERMIT_TYPEHASH", async () => {
const name = await token.name();
expect(name).to.eq("VVS Finance LPs");
expect(await token.symbol()).to.eq("VVS-LP");
expect(await token.decimals()).to.eq(18);
expect(await token.totalSupply()).to.eq(TOTAL_SUPPLY);
expect(await token.balanceOf(wallet.address)).to.eq(TOTAL_SUPPLY);
expect(await token.DOMAIN_SEPARATOR()).to.eq(
keccak256(
defaultAbiCoder.encode(
["bytes32", "bytes32", "bytes32", "uint256", "address"],
[
keccak256(
toUtf8Bytes("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
),
keccak256(toUtf8Bytes(name)),
keccak256(toUtf8Bytes("1")),
1,
token.address
]
)
)
);
expect(await token.PERMIT_TYPEHASH()).to.eq(
keccak256(toUtf8Bytes("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"))
);
});
it("approve", async () => {
await expect(token.approve(other.address, TEST_AMOUNT))
.to.emit(token, "Approval")
.withArgs(wallet.address, other.address, TEST_AMOUNT);
expect(await token.allowance(wallet.address, other.address)).to.eq(TEST_AMOUNT);
});
it("transfer", async () => {
await expect(token.transfer(other.address, TEST_AMOUNT))
.to.emit(token, "Transfer")
.withArgs(wallet.address, other.address, TEST_AMOUNT);
expect(await token.balanceOf(wallet.address)).to.eq(TOTAL_SUPPLY.sub(TEST_AMOUNT));
expect(await token.balanceOf(other.address)).to.eq(TEST_AMOUNT);
});
it("transfer:fail", async () => {
await expect(token.transfer(other.address, TOTAL_SUPPLY.add(1))).to.be.reverted; // ds-math-sub-underflow
await expect(token.connect(other).transfer(wallet.address, 1)).to.be.reverted; // ds-math-sub-underflow
});
it("transferFrom", async () => {
await token.approve(other.address, TEST_AMOUNT);
await expect(token.connect(other).transferFrom(wallet.address, other.address, TEST_AMOUNT))
.to.emit(token, "Transfer")
.withArgs(wallet.address, other.address, TEST_AMOUNT);
expect(await token.allowance(wallet.address, other.address)).to.eq(0);
expect(await token.balanceOf(wallet.address)).to.eq(TOTAL_SUPPLY.sub(TEST_AMOUNT));
expect(await token.balanceOf(other.address)).to.eq(TEST_AMOUNT);
});
it("transferFrom:max", async () => {
await token.approve(other.address, MaxUint256);
await expect(token.connect(other).transferFrom(wallet.address, other.address, TEST_AMOUNT))
.to.emit(token, "Transfer")
.withArgs(wallet.address, other.address, TEST_AMOUNT);
expect(await token.allowance(wallet.address, other.address)).to.eq(MaxUint256);
expect(await token.balanceOf(wallet.address)).to.eq(TOTAL_SUPPLY.sub(TEST_AMOUNT));
expect(await token.balanceOf(other.address)).to.eq(TEST_AMOUNT);
});
it("permit", async () => {
const nonce = await token.nonces(wallet.address);
const deadline = MaxUint256;
const digest = await getApprovalDigest(
token,
{ owner: wallet.address, spender: other.address, value: TEST_AMOUNT },
nonce,
deadline
);
const { v, r, s } = ecsign(Buffer.from(digest.slice(2), "hex"), Buffer.from(wallet.privateKey.slice(2), "hex"));
await expect(token.permit(wallet.address, other.address, TEST_AMOUNT, deadline, v, hexlify(r), hexlify(s)))
.to.emit(token, "Approval")
.withArgs(wallet.address, other.address, TEST_AMOUNT);
expect(await token.allowance(wallet.address, other.address)).to.eq(TEST_AMOUNT);
expect(await token.nonces(wallet.address)).to.eq(BigNumber.from(1));
});
});
Example #13
Source File: 124_delegable_signature.ts From fyDai with GNU General Public License v3.0 | 4 votes |
contract('Delegable with signatures', async (accounts: string[]) => {
// this is the SECOND account that buidler creates
// https://github.com/nomiclabs/buidler/blob/d399a60452f80a6e88d974b2b9205f4894a60d29/packages/buidler-core/src/internal/core/config/default-config.ts#L46
const userPrivateKey = Buffer.from('d49743deccbccc5dc7baa8e69e5be03298da8688a15dd202e20f15d5e0e9a9fb', 'hex')
const chainId = 31337 // buidlerevm chain id
let [owner, user, delegate] = accounts
let delegableContract: Contract
let name: string
beforeEach(async () => {
delegableContract = await Delegable.new({ from: owner })
name = 'Yield'
})
it('initializes SIGNATURE_TYPEHASH correctly', async () => {
assert.equal(await delegableContract.SIGNATURE_TYPEHASH(), SIGNATURE_TYPEHASH)
})
it('initializes DELEGABLE_DOMAIN correctly', async () => {
assert.equal(
await delegableContract.DELEGABLE_DOMAIN(),
getDomainSeparator(name, delegableContract.address, chainId)
)
})
it('permits and emits Delegate (replay safe)', async () => {
// Create the signature request
const signature = {
user: user,
delegate: delegate,
}
// deadline as much as you want in the future
const deadline = 100000000000000
// Get the user's signatureCount
const signatureCount = await delegableContract.signatureCount(user)
// Get the EIP712 digest
const digest = getSignatureDigest(name, delegableContract.address, chainId, signature, signatureCount, deadline)
// Sign it
// NOTE: Using web3.eth.sign will hash the message internally again which
// we do not want, so we're manually signing here
const { v, r, s } = ecsign(Buffer.from(digest.slice(2), 'hex'), userPrivateKey)
// Approve it
const receipt = await delegableContract.addDelegateBySignature(
signature.user,
signature.delegate,
deadline,
v,
r,
s,
{ from: user }
)
const event = receipt.logs[0]
// It worked!
assert.equal(event.event, 'Delegate')
assert.equal(await delegableContract.signatureCount(user), 1)
assert.equal(await delegableContract.delegated(signature.user, signature.delegate), true)
// Re-using the same sig doesn't work since the nonce has been incremented
// on the contract level for replay-protection
await expectRevert(
delegableContract.addDelegateBySignature(signature.user, signature.delegate, deadline, v, r, s),
'Delegable: Invalid signature'
)
// invalid ecrecover's return address(0x0), so we must also guarantee that
// this case fails
await expectRevert(
delegableContract.addDelegateBySignature(
'0x0000000000000000000000000000000000000000',
signature.delegate,
deadline,
'0x99',
r,
s
),
'Delegable: Invalid signature'
)
})
})