Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: generic chainlink financing adapter #329

Draft
wants to merge 4 commits into
base: financing-chainlink-adapter
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 54 additions & 28 deletions contracts/adapters/FinancingChainlink.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,23 @@ contract FinancingChainlinkContract is
MemberGuard,
AdapterGuard
{
AggregatorV3Interface internal _priceFeed;
bytes32 internal constant _PRICE_FEED_ADDRESS_CONFIG =
keccak256("finance-chainlink:price-feed:address");

//decimals from Chainlink priceFeed.decimals();

/**
* @notice choose a priceFeed contract, see https://docs.chain.link/docs/ethereum-addresses
* Aggregator: ETH/USD
* Aggregator: ETH/USD - 8 decimals
* contract address of the price feed from Chainlink
* Rinkeby Contract Address: 0x8A753747A1Fa494EC906cE90E9f37563A8AF630e
* Mainnet Contract Address: 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419
* Mainnet Contract USDC/ETH - 18 decimals: 0x986b5E1e1755e3C2440e960477f25201B0a8bbD4
*/

constructor(address feedAddress) {
_priceFeed = AggregatorV3Interface(feedAddress);
}

// constructor(address feedAddress) {
// _priceFeed = AggregatorV3Interface(feedAddress);
// }
struct ProposalDetails {
address applicant; // the proposal applicant address, can not be a reserved address
uint256 amount; // the amount requested for funding
Expand All @@ -71,6 +74,19 @@ contract FinancingChainlinkContract is
revert("fallback revert");
}

function configureDao(DaoRegistry dao, address priceFeedAddr)
external
onlyAdapter(dao)
{
AggregatorV3Interface priceFeed = AggregatorV3Interface(priceFeedAddr);
uint8 decimalsChainlink = priceFeed.decimals();
require(
decimalsChainlink != 8 && decimalsChainlink != 18,
"chainlink pricefeed is not compatible, must be 8 or 18 decimals"
);
dao.setAddressConfiguration(_PRICE_FEED_ADDRESS_CONFIG, priceFeedAddr);
}

/**
* @notice Creates and sponsors a financing proposal.
* @dev Applicant address must not be reserved.
Expand Down Expand Up @@ -143,43 +159,53 @@ contract FinancingChainlinkContract is
IVoting.VotingState.PASS,
"proposal needs to pass"
);
dao.processProposal(proposalId);
BankExtension bank = BankExtension(dao.getExtensionAddress(BANK));

//enter US Dollar = details.amount to convert it into ETH
uint256 amount = _usdToEth(details.amount);
address priceFeedAddr =
dao.getAddressConfiguration(_PRICE_FEED_ADDRESS_CONFIG);

bank.subtractFromBalance(GUILD, details.token, amount);
bank.addToBalance(details.applicant, details.token, amount);
dao.processProposal(proposalId);
BankExtension bank = BankExtension(dao.getExtensionAddress(BANK));
//Chainlink feed instance
AggregatorV3Interface priceFeed = AggregatorV3Interface(priceFeedAddr);
//check decimals to see if 8 or 18
uint8 decimalsChainlink = priceFeed.decimals();
uint256 amount = details.amount;
address token = details.token;
address applicant = details.applicant;
if (decimalsChainlink == 8) {
//enter US Dollar = details.amount and convert with _convertToWeiValue
uint256 convertedAmount = _convertToWeiValue(amount, priceFeed);
bank.subtractFromBalance(GUILD, token, convertedAmount);
bank.addToBalance(applicant, token, convertedAmount);
} else {
bank.subtractFromBalance(GUILD, token, amount);
bank.addToBalance(applicant, token, amount);
}
}

/**
* Returns the latest price from AggregatorV3Interface.sol
Chainlink returns the latest price to 8 decimials
e.g. 176471000000 = $1,764.71
/*
@param _amount = the amount in US Dollars to convert to ETH
multipliers are needed in numerator (usd to wei) and denominator
(convert result from chainlink to wei)
*/
function getLatestPrice() public view returns (int256) {
function _convertToWeiValue(uint256 amount, AggregatorV3Interface priceFeed)
internal
view
returns (uint256)
{
(
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
) = _priceFeed.latestRoundData();
return answer;
}
) = priceFeed.latestRoundData();

/*
@param _amount = the amount in US Dollars to convert to ETH
multipliers are needed in numerator (usd to wei) and denominator
(convert result from chainlink to wei)
*/
function _usdToEth(uint256 _amount) internal view returns (uint256) {
//convert int to uint
uint256 denominator = uint256(getLatestPrice());
uint256 denominator = uint256(answer);
//multipliers to ensure values calculated in wei
uint256 ethInUsdAmount =
((_amount * 1000000000000000000000) / denominator) * 100000;
((amount * 1000000000000000000000) / denominator) * 100000;
return ethInUsdAmount;
}
}
4 changes: 3 additions & 1 deletion contracts/test/FakeChainlinkPriceFeed.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ pragma solidity ^0.8.0;
import "../adapters/interfaces/chainlink/AggregatorV3Interface.sol";

contract FakeChainlinkPriceFeed is AggregatorV3Interface {
uint8 public override decimals;
function decimals() external view virtual override returns (uint8) {
return (8);
}

string public override description;

Expand Down
5 changes: 5 additions & 0 deletions test/adapters/financing-chainlink.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,4 +467,9 @@ describe("Adapter - Financing", () => {
expect(err.reason).equal("adapter not found");
}
});

it("should not be possible to import a priceFeed from Chainlink that is not 8 or 18 decimals", async () => {
console.log("write test for price feed decimals");
});

});