take balances snapshot when depositing Ether
This commit is contained in:
parent
75c6437c7b
commit
98205ca9b7
@ -8,104 +8,155 @@ import "@aragon/os/contracts/common/SafeERC20.sol";
|
|||||||
import "@aragon/os/contracts/lib/token/ERC20.sol";
|
import "@aragon/os/contracts/lib/token/ERC20.sol";
|
||||||
|
|
||||||
interface IContributor {
|
interface IContributor {
|
||||||
|
function getContributorAddressById(uint32 id) view public returns (address);
|
||||||
|
function contributorsCount() view public returns (uint32);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IToken {
|
interface IToken {
|
||||||
function balanceOf(address owner) public view returns (uint256);
|
function balanceOf(address owner) public view returns (uint256);
|
||||||
|
function totalSupply() public view returns (uint256);
|
||||||
}
|
}
|
||||||
|
|
||||||
contract Vault is EtherTokenConstant, AragonApp, DepositableStorage {
|
contract Vault is EtherTokenConstant, AragonApp, DepositableStorage {
|
||||||
using SafeERC20 for ERC20;
|
using SafeERC20 for ERC20;
|
||||||
|
|
||||||
string private constant ERROR_NOT_DEPOSITABLE = "VAULT_NOT_DEPOSITABLE";
|
string private constant ERROR_NOT_DEPOSITABLE = "VAULT_NOT_DEPOSITABLE";
|
||||||
string private constant ERROR_DEPOSIT_VALUE_ZERO = "VAULT_DEPOSIT_VALUE_ZERO";
|
string private constant ERROR_DEPOSIT_VALUE_ZERO = "VAULT_DEPOSIT_VALUE_ZERO";
|
||||||
string private constant ERROR_VALUE_MISMATCH = "VAULT_VALUE_MISMATCH";
|
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_TOKEN_TRANSFER_FROM_REVERTED = "VAULT_TOKEN_TRANSFER_FROM_REVERT";
|
||||||
|
|
||||||
uint256 private _snapshotTotalBalance;
|
uint256 private _snapshotTotalSupply;
|
||||||
|
|
||||||
mapping (address => uint256) private _snapshotBalances;
|
mapping (address => uint256) private _snapshotBalances;
|
||||||
|
|
||||||
// ensure alphabetic order
|
// ensure alphabetic order
|
||||||
enum Apps { Contribution, Contributor, Proposal, Token }
|
enum Apps { Contribution, Contributor, Proposal, Token }
|
||||||
bytes32[4] public appIds;
|
bytes32[4] public appIds;
|
||||||
|
|
||||||
event VaultDeposit(address indexed token, address indexed sender, uint256 amount);
|
event VaultDeposit(address indexed token, address indexed sender, uint256 amount);
|
||||||
|
|
||||||
function () external payable isInitialized {
|
function () external payable isInitialized {
|
||||||
_deposit(ETH, msg.value);
|
_deposit(ETH, msg.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Initialize Vault app
|
||||||
|
* @dev As an AragonApp it needs to be initialized in order for roles (`auth` and `authP`) to work
|
||||||
|
*/
|
||||||
|
function initialize(bytes32[4] _appIds) external onlyInit {
|
||||||
|
initialized();
|
||||||
|
|
||||||
|
appIds = _appIds;
|
||||||
|
setDepositable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTokenContract() 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)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContributorAddressById(uint32 contributorId) public view returns (address) {
|
||||||
|
address contributor = getContributorContract();
|
||||||
|
return IContributor(contributor).getContributorAddressById(contributorId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContributorsAddresses() internal view returns (address[]) {
|
||||||
|
address contributor = getContributorContract();
|
||||||
|
uint32 contributorsCount = IContributor(contributor).contributorsCount();
|
||||||
|
|
||||||
|
address[] memory contributorsAddresses = new address[](contributorsCount);
|
||||||
|
|
||||||
|
for(uint32 i = 1; i <= contributorsCount; i++) {
|
||||||
|
address contributorAddress = IContributor(contributor).getContributorAddressById(i);
|
||||||
|
contributorsAddresses[i-1] = contributorAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return contributorsAddresses;
|
||||||
* @notice Initialize Vault app
|
}
|
||||||
* @dev As an AragonApp it needs to be initialized in order for roles (`auth` and `authP`) to work
|
|
||||||
|
function balanceOf(address owner) public view returns (uint256) {
|
||||||
|
address token = getTokenContract();
|
||||||
|
return IToken(token).balanceOf(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
function totalSupply() public view returns (uint256) {
|
||||||
|
address token = getTokenContract();
|
||||||
|
return IToken(token).totalSupply();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @notice Deposit `_value` `_token` to the vault
|
||||||
|
* @param _token Address of the token being transferred
|
||||||
|
* @param _value Amount of tokens being transferred
|
||||||
|
*/
|
||||||
|
function deposit(address _token, uint256 _value) external payable isInitialized {
|
||||||
|
_deposit(_token, _value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function balance(address _token) public view returns (uint256) {
|
||||||
|
if (_token == ETH) {
|
||||||
|
return address(this).balance;
|
||||||
|
} else {
|
||||||
|
return ERC20(_token).staticBalanceOf(address(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Disable recovery escape hatch, as it could be used
|
||||||
|
* maliciously to transfer funds away from the vault
|
||||||
|
*/
|
||||||
|
function allowRecoverability(address) public view returns (bool) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _deposit(address _token, uint256 _value) internal {
|
||||||
|
require(isDepositable(), ERROR_NOT_DEPOSITABLE);
|
||||||
|
require(_value > 0, ERROR_DEPOSIT_VALUE_ZERO);
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (_token == ETH) {
|
||||||
|
// 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
|
||||||
|
);
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
function initialize(bytes32[4] _appIds) external onlyInit {
|
|
||||||
initialized();
|
|
||||||
|
|
||||||
appIds = _appIds;
|
if (_token == ETH) {
|
||||||
setDepositable(true);
|
// Deposit is implicit in this case
|
||||||
|
require(msg.value == _value, ERROR_VALUE_MISMATCH);
|
||||||
|
|
||||||
|
createSnapshot();
|
||||||
|
|
||||||
|
emit VaultDeposit(_token, msg.sender, _value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getTokenContract() public view returns (address) {
|
function createSnapshot() internal {
|
||||||
IKernel k = IKernel(kernel());
|
updateSnapshotTotalSupply();
|
||||||
|
updateSnapshotBalances();
|
||||||
|
}
|
||||||
|
|
||||||
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Token)]);
|
function updateSnapshotTotalSupply() internal {
|
||||||
}
|
_snapshotTotalSupply = totalSupply();
|
||||||
|
}
|
||||||
function getContributorContract() public view returns (address) {
|
|
||||||
IKernel k = IKernel(kernel());
|
function updateSnapshotBalances() internal {
|
||||||
|
address[] memory contributorsAddresses = getContributorsAddresses();
|
||||||
return k.getApp(KERNEL_APP_ADDR_NAMESPACE, appIds[uint8(Apps.Contributor)]);
|
|
||||||
}
|
for(uint32 i = 0; i < contributorsAddresses.length; i++) {
|
||||||
|
_snapshotBalances[contributorsAddresses[i]] = balanceOf(contributorsAddresses[i]);
|
||||||
/**
|
|
||||||
* @notice Deposit `_value` `_token` to the vault
|
|
||||||
* @param _token Address of the token being transferred
|
|
||||||
* @param _value Amount of tokens being transferred
|
|
||||||
*/
|
|
||||||
function deposit(address _token, uint256 _value) external payable isInitialized {
|
|
||||||
_deposit(_token, _value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function balance(address _token) public view returns (uint256) {
|
|
||||||
if (_token == ETH) {
|
|
||||||
return address(this).balance;
|
|
||||||
} else {
|
|
||||||
return ERC20(_token).staticBalanceOf(address(this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Disable recovery escape hatch, as it could be used
|
|
||||||
* maliciously to transfer funds away from the vault
|
|
||||||
*/
|
|
||||||
function allowRecoverability(address) public view returns (bool) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function _deposit(address _token, uint256 _value) internal {
|
|
||||||
require(isDepositable(), ERROR_NOT_DEPOSITABLE);
|
|
||||||
require(_value > 0, ERROR_DEPOSIT_VALUE_ZERO);
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (_token == ETH) {
|
|
||||||
// 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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (_token == ETH) {
|
|
||||||
// Deposit is implicit in this case
|
|
||||||
require(msg.value == _value, ERROR_VALUE_MISMATCH);
|
|
||||||
|
|
||||||
emit VaultDeposit(_token, msg.sender, _value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user