Skip to content

Commit

Permalink
Allow directly sending to domains to work with locked tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
area committed Dec 5, 2024
1 parent 3ad5948 commit 55a390c
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 16 deletions.
11 changes: 9 additions & 2 deletions contracts/colony/ColonyFunding.sol
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,15 @@ contract ColonyFunding is
}

// Claim funds

DomainTokenReceiver(domainTokenReceiverAddress).transferToColony(_token);
if (_token == address(0x0)) {
DomainTokenReceiver(domainTokenReceiverAddress).transferNativeToColony();
} else {
DomainTokenReceiver(domainTokenReceiverAddress).approveTokenToColony(_token);
require(
ERC20Extended(_token).transferFrom(domainTokenReceiverAddress, address(this), claimAmount),
"colony-funding-transfer-failed"
);
}
}

function tokenEarnsReputationOnPayout(address _token) internal view returns (bool) {
Expand Down
23 changes: 10 additions & 13 deletions contracts/common/DomainTokenReceiver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,15 @@ contract DomainTokenReceiver is DSAuth {
colony = _colony;
}

function transferToColony(address tokenAddress) public onlyColony {
// Transfer the token to the colony.
if (tokenAddress == address(0)) {
// slither-disable-next-line arbitrary-send-eth
payable(colony).transfer(address(this).balance);
return;
} else {
uint256 balanceToTransfer = ERC20Extended(tokenAddress).balanceOf(address(this));
require(
ERC20Extended(tokenAddress).transfer(colony, balanceToTransfer),
"domain-token-receiver-transfer-failed"
);
}
function transferNativeToColony() public onlyColony {
payable(colony).transfer(address(this).balance);
}

function approveTokenToColony(address tokenAddress) public onlyColony {
uint256 balanceToTransfer = ERC20Extended(tokenAddress).balanceOf(address(this));
require(
ERC20Extended(tokenAddress).approve(colony, balanceToTransfer),
"domain-token-receiver-approve-failed"
);
}
}
1 change: 1 addition & 0 deletions contracts/common/TokenAuthority.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ contract TokenAuthority is DSAuthority {
bytes4 mintSigOverload = bytes4(keccak256("mint(address,uint256)"));

authorizations[_colony][transferSig] = true;
authorizations[_colony][transferFromSig] = true;
authorizations[_colony][mintSig] = true;
authorizations[_colony][mintSigOverload] = true;

Expand Down
38 changes: 37 additions & 1 deletion test/contracts-network/colony-funding.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ const {
ADDRESS_ZERO,
} = require("../../helpers/constants");

const { fundColonyWithTokens, setupRandomColony, makeExpenditure, setupFundedExpenditure } = require("../../helpers/test-data-generator");
const {
fundColonyWithTokens,
setupRandomColony,
makeExpenditure,
setupFundedExpenditure,
setupRandomToken,
} = require("../../helpers/test-data-generator");
const { getTokenArgs, checkErrorRevert, web3GetBalance, removeSubdomainLimit, expectEvent, rolesToBytes32 } = require("../../helpers/test-helper");
const { setupDomainTokenReceiverResolver } = require("../../helpers/upgradable-contracts");

Expand All @@ -31,6 +37,7 @@ const IMetaColony = artifacts.require("IMetaColony");
const Token = artifacts.require("Token");
const Resolver = artifacts.require("Resolver");
const DomainTokenReceiver = artifacts.require("DomainTokenReceiver");
const TokenAuthority = artifacts.require("contracts/common/TokenAuthority.sol:TokenAuthority");

contract("Colony Funding", (accounts) => {
const MANAGER = accounts[0];
Expand Down Expand Up @@ -606,6 +613,35 @@ contract("Colony Funding", (accounts) => {
expect(nonRewardPotsTotalAfter.sub(nonRewardPotsTotalBefore)).to.eq.BN(99);
});

it("should allow a locked token to be directly sent to a domain", async () => {
// Get address for domain 2
await colony.addDomain(1, UINT256_MAX, 1);
const receiverAddress = await colonyNetwork.getDomainTokenReceiverAddress(colony.address, 2);

// Send 100 wei
const otherToken2 = await setupRandomToken(true);
const tokenLockingAddress = await colonyNetwork.getTokenLocking();
const tokenAuthority = await TokenAuthority.new(otherToken2.address, colony.address, [tokenLockingAddress]);
await otherToken2.setAuthority(tokenAuthority.address);

await otherToken2.mint(receiverAddress, 100);

const domain = await colony.getDomain(2);
const domainPotBalanceBefore = await colony.getFundingPotBalance(domain.fundingPotId, otherToken2.address);
const nonRewardPotsTotalBefore = await colony.getNonRewardPotsTotal(otherToken2.address);

// Claim the funds
const tx = await colony.claimDomainFunds(otherToken2.address, 2);
await expectEvent(tx, "DomainFundsClaimed", [MANAGER, otherToken2.address, 2, 1, 99]);

const domainPotBalanceAfter = await colony.getFundingPotBalance(domain.fundingPotId, otherToken2.address);
const nonRewardPotsTotalAfter = await colony.getNonRewardPotsTotal(otherToken2.address);

// Check the balance of the domain
expect(domainPotBalanceAfter.sub(domainPotBalanceBefore)).to.eq.BN(99);
expect(nonRewardPotsTotalAfter.sub(nonRewardPotsTotalBefore)).to.eq.BN(99);
});

it("should not allow someone to call transferToColonyDirectly, which would mess up bookkeeping", async () => {
await colony.addDomain(1, UINT256_MAX, 1);
const receiverAddress = await colonyNetwork.getDomainTokenReceiverAddress(colony.address, 2);
Expand Down

0 comments on commit 55a390c

Please sign in to comment.