contract DFOBasedFixedInflationExtension {
string private constant FUNCTIONALITY_NAME = "manageFixedInflation";
address private _fixedInflationContract;
bool public override active;
modifier fixedInflationOnly() {
require(_fixedInflationContract == msg.sender, "Unauthorized");
receive() external payable {
require(_isFromDFO(msg.sender), "Unauthorized");
function init(address doubleProxyAddress) override public {
require(_host == address(0), "Already init");
require((_host = doubleProxyAddress) != address(0), "blank host");
_fixedInflationContract = msg.sender;
function data() view public override returns(address fixedInflationContract, address host) {
return(_fixedInflationContract, _host);
function setHost(address host) public virtual override hostOnly {
function setActive(bool _active) public override virtual hostOnly {
function receiveTokens(address[] memory tokenAddresses, uint256[] memory transferAmounts, uint256[] memory amountsToMint) public override fixedInflationOnly {
IMVDProxy(IDoubleProxy(_host).proxy()).submit(FUNCTIONALITY_NAME, abi.encode(address(0), 0, tokenAddresses, transferAmounts, amountsToMint, _fixedInflationContract));
function setEntry(FixedInflationEntry memory newEntry, FixedInflationOperation[] memory newOperations) public override hostOnly {
IFixedInflation(_fixedInflationContract).setEntry(newEntry, newOperations);
function flushBack(address[] memory tokenAddresses) public override hostOnly {
IFixedInflation(_fixedInflationContract).flushBack(tokenAddresses);
address walletAddress = _getDFOWallet();
for(uint256 i = 0; i < tokenAddresses.length; i++) {
_transferTo(tokenAddresses[i], walletAddress, _balanceOf(tokenAddresses[i]));
function deactivationByFailure() public override fixedInflationOnly {
function _getFunctionalityAddress() private view returns(address functionalityAddress) {
(functionalityAddress,,,,) = IMVDFunctionalitiesManager(IMVDProxy(IDoubleProxy(_host).proxy()).getMVDFunctionalitiesManagerAddress()).getFunctionalityData(FUNCTIONALITY_NAME);
function _getDFOWallet() private view returns(address) {
return IMVDProxy(IDoubleProxy(_host).proxy()).getMVDWalletAddress();
function _isFromDFO(address sender) private view returns(bool) {
return IMVDFunctionalitiesManager(IMVDProxy(IDoubleProxy(_host).proxy()).getMVDFunctionalitiesManagerAddress()).isAuthorizedFunctionality(sender);
function _balanceOf(address tokenAddress) private view returns (uint256) {
if(tokenAddress == address(0)) {
return address(this).balance;
return IERC20(tokenAddress).balanceOf(address(this));
function _transferTo(address erc20TokenAddress, address to, uint256 value) private {
if(erc20TokenAddress == address(0)) {
(bool result,) = to.call{value:value}("");
require(result, "ETH transfer failed");
_safeTransfer(erc20TokenAddress, to, value);
function _safeTransfer(address erc20TokenAddress, address to, uint256 value) private {
bytes memory returnData = _call(erc20TokenAddress, abi.encodeWithSelector(IERC20(erc20TokenAddress).transfer.selector, to, value));
require(returnData.length == 0 || abi.decode(returnData, (bool)), 'TRANSFER_FAILED');
function _call(address location, bytes memory payload) private returns(bytes memory returnData) {
let result := call(gas(), location, 0, add(payload, 0x20), mload(payload), 0, 0)
let size := returndatasize()
returnData := mload(0x40)
let returnDataPayloadStart := add(returnData, 0x20)
returndatacopy(returnDataPayloadStart, 0, size)
mstore(0x40, add(returnDataPayloadStart, size))
switch result case 0 {revert(returnDataPayloadStart, size)}