-
Notifications
You must be signed in to change notification settings - Fork 45
Raise transfer stipend #672
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -90,6 +90,7 @@ export default { | |
}, | ||
networks: { | ||
hardhat: { | ||
hardfork: "berlin", | ||
blockGasLimit: 12.5e6, | ||
}, | ||
mainnet: { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
pragma solidity ^0.7.6; | ||
|
||
contract FallbackWriteStorage { | ||
uint256 public receiveCount; | ||
|
||
receive() external payable { | ||
receiveCount += 1; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,14 @@ | ||
import IERC20 from "@openzeppelin/contracts/build/contracts/IERC20.json"; | ||
import { expect } from "chai"; | ||
import { MockContract } from "ethereum-waffle"; | ||
import { BigNumber, Contract } from "ethers"; | ||
import { BigNumber, Contract, ContractFactory } from "ethers"; | ||
import { artifacts, ethers, waffle } from "hardhat"; | ||
|
||
import { BUY_ETH_ADDRESS } from "../src/ts"; | ||
|
||
import { UserBalanceOpKind } from "./balancer"; | ||
import { OrderBalanceId } from "./encoding"; | ||
import { GnosisSafeManager } from "./safe"; | ||
|
||
describe("GPv2Transfer", () => { | ||
const [deployer, recipient, funder, ...traders] = | ||
|
@@ -17,6 +18,9 @@ describe("GPv2Transfer", () => { | |
let vault: MockContract; | ||
let token: MockContract; | ||
|
||
let NonPayable: ContractFactory; | ||
let FallbackWriteStorage: ContractFactory; | ||
|
||
beforeEach(async () => { | ||
const GPv2Transfer = await ethers.getContractFactory( | ||
"GPv2TransferTestInterface", | ||
|
@@ -26,6 +30,11 @@ describe("GPv2Transfer", () => { | |
const IVault = await artifacts.readArtifact("IVault"); | ||
vault = await waffle.deployMockContract(deployer, IVault.abi); | ||
token = await waffle.deployMockContract(deployer, IERC20.abi); | ||
|
||
NonPayable = await ethers.getContractFactory("NonPayable"); | ||
FallbackWriteStorage = await ethers.getContractFactory( | ||
"FallbackWriteStorage", | ||
); | ||
}); | ||
|
||
const amount = ethers.utils.parseEther("0.1337"); | ||
|
@@ -508,6 +517,77 @@ describe("GPv2Transfer", () => { | |
); | ||
}); | ||
|
||
it("should transfer Ether to a Smart Contract wallet", async () => { | ||
await funder.sendTransaction({ | ||
to: transfer.address, | ||
value: amount, | ||
}); | ||
|
||
const safeManager = await GnosisSafeManager.init(deployer); | ||
const safe = await safeManager.newSafe([traders[0].address], 1); | ||
|
||
await transfer.transferToAccountsTest(vault.address, [ | ||
{ | ||
account: safe.address, | ||
token: BUY_ETH_ADDRESS, | ||
amount, | ||
balance: OrderBalanceId.ERC20, | ||
}, | ||
]); | ||
|
||
expect(await ethers.provider.getBalance(safe.address)).to.deep.equal( | ||
amount, | ||
); | ||
}); | ||
|
||
it("should revert when transfering Ether to contract that reverts", async () => { | ||
await funder.sendTransaction({ | ||
to: transfer.address, | ||
value: amount, | ||
}); | ||
|
||
const smartWallet = await NonPayable.deploy(); | ||
await expect( | ||
transfer.transferToAccountsTest(vault.address, [ | ||
{ | ||
account: smartWallet.address, | ||
token: BUY_ETH_ADDRESS, | ||
amount, | ||
balance: OrderBalanceId.ERC20, | ||
}, | ||
]), | ||
).to.be.reverted; | ||
}); | ||
|
||
it("should revert when transfering Ether to contract writes storage", async () => { | ||
await funder.sendTransaction({ | ||
to: transfer.address, | ||
value: amount, | ||
}); | ||
|
||
const smartWallet = await FallbackWriteStorage.deploy(); | ||
|
||
await expect( | ||
funder.sendTransaction({ | ||
to: smartWallet.address, | ||
value: 1, | ||
}), | ||
).to.not.be.reverted; | ||
expect(await smartWallet.receiveCount()).to.equal(1); | ||
|
||
await expect( | ||
transfer.transferToAccountsTest(vault.address, [ | ||
{ | ||
account: smartWallet.address, | ||
token: BUY_ETH_ADDRESS, | ||
amount, | ||
balance: OrderBalanceId.ERC20, | ||
}, | ||
]), | ||
).to.be.reverted; | ||
expect(await smartWallet.receiveCount()).to.not.equal(2); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤷 - |
||
}); | ||
|
||
it("should transfer many external and internal amounts to recipient", async () => { | ||
// NOTE: Make sure we have enough traders for our test :) | ||
expect(traders).to.have.length.above(5); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import GnosisSafe from "@gnosis.pm/safe-contracts/build/artifacts/contracts/GnosisSafe.sol/GnosisSafe.json"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Mentioned in the PR description ... Everything looks good There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: you could pull the ABI from https://github.com/gnosis/safe-deployments but we are currently missing the deployment code in the deployments which might be interesting for tests ... I opened an issue for this: safe-global/safe-deployments#8 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Edit: was not even aware that we include the hardhat build artifacts in the npm release 😬 |
||
import CompatibilityFallbackHandler from "@gnosis.pm/safe-contracts/build/artifacts/contracts/handler/CompatibilityFallbackHandler.sol/CompatibilityFallbackHandler.json"; | ||
import GnosisSafeProxyFactory from "@gnosis.pm/safe-contracts/build/artifacts/contracts/proxies/GnosisSafeProxyFactory.sol/GnosisSafeProxyFactory.json"; | ||
import { Signer, Contract } from "ethers"; | ||
import { ethers, waffle } from "hardhat"; | ||
|
||
export class GnosisSafeManager { | ||
constructor( | ||
readonly deployer: Signer, | ||
readonly masterCopy: Contract, | ||
readonly signingFallback: Contract, | ||
readonly proxyFactory: Contract, | ||
) {} | ||
|
||
static async init(deployer: Signer): Promise<GnosisSafeManager> { | ||
const masterCopy = await waffle.deployContract(deployer, GnosisSafe); | ||
const proxyFactory = await waffle.deployContract( | ||
deployer, | ||
GnosisSafeProxyFactory, | ||
); | ||
const signingFallback = await waffle.deployContract( | ||
deployer, | ||
CompatibilityFallbackHandler, | ||
); | ||
return new GnosisSafeManager( | ||
deployer, | ||
masterCopy, | ||
signingFallback, | ||
proxyFactory, | ||
); | ||
} | ||
|
||
async newSafe( | ||
owners: string[], | ||
threshold: number, | ||
fallback = ethers.constants.AddressZero, | ||
): Promise<Contract> { | ||
const proxyAddress = await this.proxyFactory.callStatic.createProxy( | ||
this.masterCopy.address, | ||
"0x", | ||
); | ||
await this.proxyFactory.createProxy(this.masterCopy.address, "0x"); | ||
const safe = await ethers.getContractAt(GnosisSafe.abi, proxyAddress); | ||
await safe.setup( | ||
owners, | ||
threshold, | ||
ethers.constants.AddressZero, | ||
"0x", | ||
fallback, | ||
ethers.constants.AddressZero, | ||
0, | ||
ethers.constants.AddressZero, | ||
); | ||
return safe; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see this should be the default value, is this to "freeze" the fork in case there are incompatible changes in a future fork?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that was left over when I was trying some stuff out. I'll remove it. In fact, the block gas limit setting can also be removed as the default is the same here.