diff --git a/contracts/Wallet.sol b/contracts/Wallet.sol index 66debb7..8e561c5 100644 --- a/contracts/Wallet.sol +++ b/contracts/Wallet.sol @@ -12,16 +12,6 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; * That address is specified by the `WalletFactory` contract. */ contract Wallet { - /** - * @dev Event fired upon receiving `amount` ether from `sender`. - */ - event EtherReceived(address indexed sender, uint amount); - - /** - * @dev Event fired upon sending `amount` ether to `receiver`. - */ - event EtherSent(address indexed receiver, uint amount); - WalletFactory public factory; /** @@ -50,7 +40,6 @@ contract Wallet { function collectEther() public returns (uint) { uint balance = address(this).balance; master().transfer(balance); - emit EtherSent(master(), balance); return balance; } @@ -71,7 +60,7 @@ contract Wallet { /** * @dev Collects several tokens and ether at once and sends it all to the master address. - */ + */ function collectMany(address[] calldata _assets) public returns (uint[] memory) { require(_assets.length > 0, "Wallet: at least one asset must be specified"); @@ -86,6 +75,6 @@ contract Wallet { * @dev Method to log whenever ether is received by this contract. */ receive() external payable { - emit EtherReceived(msg.sender, msg.value); + factory.notifyEtherReceived(msg.sender, msg.value); } } diff --git a/contracts/WalletFactory.sol b/contracts/WalletFactory.sol index 30d27d6..50a8866 100644 --- a/contracts/WalletFactory.sol +++ b/contracts/WalletFactory.sol @@ -23,6 +23,11 @@ contract WalletFactory is Ownable { */ event AddressGenerated(address indexed generatedAddress); + /** + * @dev Event fired upon receiving `amount` ether from `sender`. + */ + event EtherReceived(address indexed sender, address indexed receiver, uint amount); + /** * @dev Address where all funds coming from `Wallet` contracts will be collected in. */ @@ -33,6 +38,11 @@ contract WalletFactory is Ownable { * in the process. */ address public template; + + /** + * Stored whether an address has been generated by this contract or not. + */ + mapping(address => bool) generatedAddresses; constructor(address payable _master, address _template) { require(_template != address(0), "WalletFactory: template address cannot be zero"); @@ -59,6 +69,7 @@ contract WalletFactory is Ownable { function generate() public returns (address) { address clone = template.clone(); Wallet(payable(clone)).setup(); + generatedAddresses[clone] = true; emit AddressGenerated(clone); return clone; } @@ -69,10 +80,16 @@ contract WalletFactory is Ownable { function generateMany(uint _numWallets) public returns (address[] memory) { require(_numWallets > 0, "WalletFactory: you must specify a number of wallets greater than zero"); - address[] memory generatedAddresses = new address[](_numWallets); + address[] memory newAddresses = new address[](_numWallets); for (uint i = 0; i < _numWallets; i++) { - generatedAddresses[i] = generate(); + newAddresses[i] = generate(); } - return generatedAddresses; + return newAddresses; + } + + function notifyEtherReceived(address _sender, uint _amount) public { + require(generatedAddresses[msg.sender], "WalletFactory: receiver has not been generated by the factory"); + + emit EtherReceived(_sender, msg.sender, _amount); } } diff --git a/package.json b/package.json index dffbf21..d0cfc07 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "coverage": "truffle run coverage" }, "dependencies": { - "@openzeppelin/contracts": "^4.2.0" + "@openzeppelin/contracts": "^4.3.2" }, "devDependencies": { "solidity-coverage": "^0.7.16", diff --git a/test/wallet.js b/test/wallet.js index c132fc0..98a2c93 100644 --- a/test/wallet.js +++ b/test/wallet.js @@ -123,9 +123,10 @@ contract('WalletFactory', (accounts) => { value: amount, }) assert.isOk(tx.status) - const result = await truffleAssert.createTransactionResult(walletInstance, tx.transactionHash) + const result = await truffleAssert.createTransactionResult(walletFactoryInstance, tx.transactionHash) truffleAssert.eventEmitted(result, 'EtherReceived', { sender, + receiver: walletInstance.address, amount, }) const balance = await web3.eth.getBalance(walletInstance.address) @@ -148,10 +149,6 @@ contract('WalletFactory', (accounts) => { // collecting the balance const tx = await walletInstance.collectEther() assert.isOk(tx.receipt.status) - truffleAssert.eventEmitted(tx, 'EtherSent', { - receiver: master, - amount, - }) // checking balances after const walletBalanceAfter = await web3.eth.getBalance(walletInstance.address) @@ -219,10 +216,6 @@ contract('WalletFactory', (accounts) => { // collecting funds const tx = await walletInstance.collectMany([ZERO_ADDRESS, tokenInstance.address]) assert.isOk(tx.receipt.status) - truffleAssert.eventEmitted(tx, 'EtherSent', { - receiver: master, - amount, - }) const result = await truffleAssert.createTransactionResult(tokenInstance, tx.receipt.transactionHash) truffleAssert.eventEmitted(result, 'Transfer', { from: walletInstance.address, diff --git a/yarn.lock b/yarn.lock index 74dd0aa..f8959d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1393,10 +1393,10 @@ find-up "^4.1.0" fs-extra "^8.1.0" -"@openzeppelin/contracts@^4.2.0": - version "4.2.0" - resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.2.0.tgz#260d921d99356e48013d9d760caaa6cea35dc642" - integrity sha512-LD4NnkKpHHSMo5z9MvFsG4g1xxZUDqV3A3Futu3nvyfs4wPwXxqOgMaxOoa2PeyGL2VNeSlbxT54enbQzGcgJQ== +"@openzeppelin/contracts@^4.3.2": + version "4.3.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.3.2.tgz#ff80affd6d352dbe1bbc5b4e1833c41afd6283b6" + integrity sha512-AybF1cesONZStg5kWf6ao9OlqTZuPqddvprc0ky7lrUVOjXeKpmQ2Y9FK+6ygxasb+4aic4O5pneFBfwVsRRRg== "@openzeppelin/test-helpers@^0.5.12": version "0.5.12"