The Scriptorium
Smart Assembly code templates and tools for on-chain development in Eve Frontier.
← Back to Example Code
Tribe Treasury
Tribe ManagementA simple multi-sig-style tribal treasury. Officers can propose withdrawals, and a configurable number of approvals are required before funds are released. Tracks deposit and withdrawal history.
tribetreasurymulti-siggovernance
tribe-treasury.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/**
* @title TribeTreasury
* @notice Simple multi-sig treasury for tribal fund management.
*/
contract TribeTreasury {
address public chief;
mapping(address => bool) public officers;
uint256 public requiredApprovals;
struct Proposal {
address recipient;
uint256 amount;
string reason;
uint256 approvalCount;
bool executed;
mapping(address => bool) approvals;
}
uint256 public proposalCount;
mapping(uint256 => Proposal) public proposals;
event Deposited(address indexed from, uint256 amount);
event ProposalCreated(uint256 indexed id, address recipient, uint256 amount);
event ProposalApproved(uint256 indexed id, address approver);
event ProposalExecuted(uint256 indexed id, address recipient, uint256 amount);
constructor(uint256 _requiredApprovals) {
chief = msg.sender;
officers[msg.sender] = true;
requiredApprovals = _requiredApprovals;
}
modifier onlyChief() {
require(msg.sender == chief, "Not chief");
_;
}
modifier onlyOfficer() {
require(officers[msg.sender], "Not an officer");
_;
}
function addOfficer(address _officer) external onlyChief {
officers[_officer] = true;
}
function removeOfficer(address _officer) external onlyChief {
require(_officer != chief, "Cannot remove chief");
officers[_officer] = false;
}
function deposit() external payable {
require(msg.value > 0, "Must send value");
emit Deposited(msg.sender, msg.value);
}
function propose(
address _recipient,
uint256 _amount,
string calldata _reason
) external onlyOfficer returns (uint256) {
require(_amount <= address(this).balance, "Insufficient balance");
uint256 id = proposalCount++;
Proposal storage p = proposals[id];
p.recipient = _recipient;
p.amount = _amount;
p.reason = _reason;
emit ProposalCreated(id, _recipient, _amount);
return id;
}
function approve(uint256 _id) external onlyOfficer {
Proposal storage p = proposals[_id];
require(!p.executed, "Already executed");
require(!p.approvals[msg.sender], "Already approved");
p.approvals[msg.sender] = true;
p.approvalCount++;
emit ProposalApproved(_id, msg.sender);
if (p.approvalCount >= requiredApprovals) {
p.executed = true;
(bool sent, ) = p.recipient.call{value: p.amount}("");
require(sent, "Transfer failed");
emit ProposalExecuted(_id, p.recipient, p.amount);
}
}
receive() external payable {
emit Deposited(msg.sender, msg.value);
}
}