1
0
forked from mico/idle_moloch
idle_moloch/lib/Baal/contracts/tools/TributeMinion.sol
2024-11-01 11:55:27 +01:00

177 lines
4.5 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
import "../Baal.sol";
interface IERC20 {
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}
contract TributeMinion {
event TributeProposal(
address indexed baal,
address token,
uint256 amount,
address recipient,
uint256 proposalId
);
struct Escrow {
address token;
address applicant;
uint256 amount;
bool released;
address safe;
}
mapping(address => mapping(uint256 => Escrow)) public escrows;
event EscrowReleased(
address indexed baal,
uint32 proposalId,
address applicant,
address safe,
uint256 amount
);
function encodeTributeProposal(
address baal,
uint256 shares,
uint256 loot,
address recipient,
uint32 proposalId,
address escrow
) public pure returns (bytes memory) {
// Workaround for solidity dynamic memory array
address[] memory _recipients = new address[](1);
_recipients[0] = recipient;
bytes memory _releaseEscrow = abi.encodeWithSignature(
"releaseEscrow(address,uint32)",
baal,
proposalId
);
bytes memory tributeMultisend = abi.encodePacked(
uint8(0),
escrow,
uint256(0),
uint256(_releaseEscrow.length),
bytes(_releaseEscrow)
);
if (shares > 0) {
// Workaround for solidity dynamic memory array
uint256[] memory _shares = new uint256[](1);
_shares[0] = shares;
bytes memory _issueShares = abi.encodeWithSignature(
"mintShares(address[],uint256[])",
_recipients,
_shares
);
tributeMultisend = abi.encodePacked(
tributeMultisend,
uint8(0),
baal,
uint256(0),
uint256(_issueShares.length),
bytes(_issueShares)
);
}
if (loot > 0) {
// Workaround for solidity dynamic memory array
uint256[] memory _loot = new uint256[](1);
_loot[0] = loot;
bytes memory _issueLoot = abi.encodeWithSignature(
"mintLoot(address[],uint256[])",
_recipients,
_loot
);
tributeMultisend = abi.encodePacked(
tributeMultisend,
uint8(0),
address(baal),
uint256(0),
uint256(_issueLoot.length),
bytes(_issueLoot)
);
}
bytes memory _multisendAction = abi.encodeWithSignature(
"multiSend(bytes)",
tributeMultisend
);
return _multisendAction;
}
function submitTributeProposal(
Baal baal,
address token,
uint256 amount,
uint256 shares,
uint256 loot,
uint32 expiration,
uint256 baalgas,
string memory details
) external payable {
uint32 proposalId = baal.proposalCount() + 1;
bytes memory encodedProposal = encodeTributeProposal(
address(baal),
shares,
loot,
msg.sender,
proposalId,
address(this)
);
escrows[address(baal)][proposalId] = Escrow(
token,
msg.sender,
amount,
false,
baal.target()
);
baal.submitProposal{value:msg.value}(encodedProposal, expiration, baalgas, details);
emit TributeProposal(
address(baal),
token,
amount,
msg.sender,
proposalId
);
}
function releaseEscrow(address _baal, uint32 _proposalId) external {
Baal baal = Baal(_baal);
Escrow storage escrow = escrows[address(baal)][_proposalId];
require(!escrow.released, "Already released");
bool[4] memory status = baal.getProposalStatus(_proposalId);
require(status[2], "Not passed");
escrow.released = true;
IERC20 token = IERC20(escrow.token);
emit EscrowReleased(
_baal,
_proposalId,
escrow.applicant,
escrow.safe,
escrow.amount
);
require(
token.transferFrom(escrow.applicant, escrow.safe, escrow.amount),
"Transfer failed"
);
}
}