96 lines
3.1 KiB
Solidity
96 lines
3.1 KiB
Solidity
pragma solidity ^0.4.24;
|
|
|
|
import "@aragon/os/contracts/apps/AragonApp.sol";
|
|
import "@aragon/os/contracts/kernel/IKernel.sol";
|
|
|
|
contract Reimbursement is AragonApp {
|
|
bytes32 public constant ADD_REIMBURSEMENT_ROLE = keccak256("ADD_REIMBURSEMENT_ROLE");
|
|
bytes32 public constant VETO_REIMBURSEMENT_ROLE = keccak256("VETO_REIMBURSEMENT_ROLE");
|
|
|
|
struct ReimbursementData {
|
|
address recordedBy;
|
|
uint32 contributorId;
|
|
uint256 amount;
|
|
address token;
|
|
bytes32 hashDigest;
|
|
uint8 hashFunction;
|
|
uint8 hashSize;
|
|
uint256 confirmedAtBlock;
|
|
bool vetoed;
|
|
bool exists;
|
|
}
|
|
|
|
mapping(uint32 => ReimbursementData) public reimbursements;
|
|
uint32 public reimbursementsCount;
|
|
|
|
uint32 public blocksToWait;
|
|
|
|
event ReimbursementAdded(uint32 id, address indexed addedByAccount, uint256 amount);
|
|
event ReimbursementVetoed(uint32 id, address vetoedByAccount);
|
|
|
|
// TODO: remove _appIds when those are removed from the kreditskit
|
|
// using the appids to find other apps is wrong according to aragon
|
|
function initialize(bytes32[5] _appIds) public onlyInit {
|
|
blocksToWait = 40320; // 7 days; 15 seconds block time
|
|
initialized();
|
|
}
|
|
|
|
function totalAmount(bool confirmedOnly) public view returns (uint256 amount) {
|
|
for (uint32 i = 1; i <= reimbursementsCount; i++) {
|
|
ReimbursementData memory r = reimbursements[i];
|
|
if (!r.vetoed && (block.number >= r.confirmedAtBlock || !confirmedOnly)) {
|
|
amount += r.amount; // should use safemath
|
|
}
|
|
}
|
|
}
|
|
|
|
function get(uint32 reimbursementId) public view returns (uint32 id, address recordedBy, uint32 contributorId, uint256 amount, address token, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize, uint256 confirmedAtBlock, bool exists, bool vetoed) {
|
|
id = reimbursementId;
|
|
ReimbursementData storage r = reimbursements[id];
|
|
return (
|
|
id,
|
|
r.recordedBy,
|
|
r.contributorId,
|
|
r.amount,
|
|
r.token,
|
|
r.hashDigest,
|
|
r.hashFunction,
|
|
r.hashSize,
|
|
r.confirmedAtBlock,
|
|
r.exists,
|
|
r.vetoed
|
|
);
|
|
}
|
|
|
|
function add(uint256 amount, address token, uint32 contributorId, bytes32 hashDigest, uint8 hashFunction, uint8 hashSize) public isInitialized auth(ADD_REIMBURSEMENT_ROLE) {
|
|
uint32 reimbursementId = reimbursementsCount + 1;
|
|
ReimbursementData storage r = reimbursements[reimbursementId];
|
|
r.recordedBy = msg.sender;
|
|
r.exists = true;
|
|
r.amount = amount;
|
|
r.token = token;
|
|
r.contributorId = contributorId;
|
|
r.hashDigest = hashDigest;
|
|
r.hashFunction = hashFunction;
|
|
r.hashSize = hashSize;
|
|
r.confirmedAtBlock = block.number + blocksToWait;
|
|
|
|
reimbursementsCount++;
|
|
|
|
emit ReimbursementAdded(reimbursementId, msg.sender, amount);
|
|
}
|
|
|
|
function veto(uint32 reimbursementId) public isInitialized auth(VETO_REIMBURSEMENT_ROLE) {
|
|
ReimbursementData storage r = reimbursements[reimbursementId];
|
|
require(r.exists, 'NOT_FOUND');
|
|
require(block.number < r.confirmedAtBlock, 'VETO_PERIOD_ENDED');
|
|
r.vetoed = true;
|
|
|
|
emit ReimbursementVetoed(reimbursementId, msg.sender);
|
|
}
|
|
|
|
function exists(uint32 reimbursementId) public view returns (bool) {
|
|
return reimbursements[reimbursementId].exists;
|
|
}
|
|
}
|