diff --git a/apps/vault/contracts/Vault.sol b/apps/vault/contracts/Vault.sol index 1878b4f..2e3eeff 100644 --- a/apps/vault/contracts/Vault.sol +++ b/apps/vault/contracts/Vault.sol @@ -20,10 +20,15 @@ interface IToken { contract Vault is EtherTokenConstant, AragonApp, DepositableStorage { using SafeERC20 for ERC20; + bytes32 public constant TRANSFER_ROLE = keccak256("TRANSFER_ROLE"); + string private constant ERROR_NOT_DEPOSITABLE = "VAULT_NOT_DEPOSITABLE"; string private constant ERROR_DEPOSIT_VALUE_ZERO = "VAULT_DEPOSIT_VALUE_ZERO"; string private constant ERROR_VALUE_MISMATCH = "VAULT_VALUE_MISMATCH"; string private constant ERROR_TOKEN_TRANSFER_FROM_REVERTED = "VAULT_TOKEN_TRANSFER_FROM_REVERT"; + string private constant ERROR_TRANSFER_VALUE_ZERO = "VAULT_TRANSFER_VALUE_ZERO"; + string private constant ERROR_SEND_REVERTED = "VAULT_SEND_REVERTED"; + string private constant ERROR_TOKEN_TRANSFER_REVERTED = "VAULT_TOKEN_TRANSFER_REVERTED"; uint256 private _snapshotTotalSupply; @@ -34,6 +39,7 @@ contract Vault is EtherTokenConstant, AragonApp, DepositableStorage { bytes32[4] public appIds; event VaultDeposit(address indexed token, address indexed sender, uint256 amount); + event VaultTransfer(address indexed token, address indexed to, uint256 amount); function () external payable isInitialized { _deposit(ETH, msg.value); @@ -50,25 +56,18 @@ contract Vault is EtherTokenConstant, AragonApp, DepositableStorage { setDepositable(true); } - function getTokenContract() public view returns (address) { + function getContract(uint8 appId) public view returns (address) { IKernel k = IKernel(kernel()); - - return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Token)]); - } - - function getContributorContract() public view returns (address) { - IKernel k = IKernel(kernel()); - - return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contributor)]); + return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[appId]); } function getContributorAddressById(uint32 contributorId) public view returns (address) { - address contributor = getContributorContract(); + address contributor = getContract(uint8(Apps.Contributor)); return IContributor(contributor).getContributorAddressById(contributorId); } function getContributorsAddresses() internal view returns (address[]) { - address contributor = getContributorContract(); + address contributor = getContract(uint8(Apps.Contributor)); uint32 contributorsCount = IContributor(contributor).contributorsCount(); address[] memory contributorsAddresses = new address[](contributorsCount); @@ -82,12 +81,12 @@ contract Vault is EtherTokenConstant, AragonApp, DepositableStorage { } function balanceOf(address owner) public view returns (uint256) { - address token = getTokenContract(); + address token = getContract(uint8(Apps.Token)); return IToken(token).balanceOf(owner); } function totalSupply() public view returns (uint256) { - address token = getTokenContract(); + address token = getContract(uint8(Apps.Token)); return IToken(token).totalSupply(); } @@ -121,35 +120,39 @@ contract Vault is EtherTokenConstant, AragonApp, DepositableStorage { require(_value > 0, ERROR_DEPOSIT_VALUE_ZERO); if (_token == ETH) { - // Deposit is implicit in this case - require(msg.value == _value, ERROR_VALUE_MISMATCH); - - createSnapshot(); - - emit VaultDeposit(_token, msg.sender, _value); + // Deposit is implicit in this case + require(msg.value == _value, ERROR_VALUE_MISMATCH); } else { require( ERC20(_token).safeTransferFrom(msg.sender, address(this), _value), ERROR_TOKEN_TRANSFER_FROM_REVERTED ); } + + emit VaultDeposit(_token, msg.sender, _value); } + + /** + * @notice Transfer `_value` `_token` from the Vault to `_to` + * @param _token Address of the token being transferred + * @param _to Address of the recipient of tokens + * @param _value Amount of tokens being transferred + */ + /* solium-disable-next-line function-order */ + function transfer(address _token, address _to, uint256 _value) + external + authP(TRANSFER_ROLE, arr(_token, _to, _value)) + { + require(_value > 0, ERROR_TRANSFER_VALUE_ZERO); - function createSnapshot() internal { - updateSnapshotTotalSupply(); - updateSnapshotBalances(); - } - - function updateSnapshotTotalSupply() internal { - _snapshotTotalSupply = totalSupply(); - } - - function updateSnapshotBalances() internal { - address[] memory contributorsAddresses = getContributorsAddresses(); - - for(uint32 i = 0; i < contributorsAddresses.length; i++) { - _snapshotBalances[contributorsAddresses[i]] = balanceOf(contributorsAddresses[i]); + if (_token == ETH) { + require(_to.send(_value), ERROR_SEND_REVERTED); + } else { + require(ERC20(_token).safeTransfer(_to, _value), ERROR_TOKEN_TRANSFER_REVERTED); } + + emit VaultTransfer(_token, _to, _value); } + } \ No newline at end of file