diff --git a/abis/Balancer.json b/abis/Balancer.json new file mode 100644 index 0000000..544d405 --- /dev/null +++ b/abis/Balancer.json @@ -0,0 +1,132 @@ +[ + { + "inputs": [ + { "internalType": "contract IVault", "name": "_vault", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newFlashLoanFeePercentage", + "type": "uint256" + } + ], + "name": "FlashLoanFeePercentageChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "newSwapFeePercentage", + "type": "uint256" + } + ], + "name": "SwapFeePercentageChanged", + "type": "event" + }, + { + "inputs": [ + { "internalType": "bytes4", "name": "selector", "type": "bytes4" } + ], + "name": "getActionId", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAuthorizer", + "outputs": [ + { "internalType": "contract IAuthorizer", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "getCollectedFeeAmounts", + "outputs": [ + { "internalType": "uint256[]", "name": "feeAmounts", "type": "uint256[]" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getFlashLoanFeePercentage", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSwapFeePercentage", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newFlashLoanFeePercentage", + "type": "uint256" + } + ], + "name": "setFlashLoanFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newSwapFeePercentage", + "type": "uint256" + } + ], + "name": "setSwapFeePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vault", + "outputs": [ + { "internalType": "contract IVault", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20[]", + "name": "tokens", + "type": "address[]" + }, + { "internalType": "uint256[]", "name": "amounts", "type": "uint256[]" }, + { "internalType": "address", "name": "recipient", "type": "address" } + ], + "name": "withdrawCollectedFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/abis/Maker.json b/abis/Maker.json new file mode 100644 index 0000000..15c5338 --- /dev/null +++ b/abis/Maker.json @@ -0,0 +1,268 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "daiJoin_", "type": "address" }, + { "internalType": "address", "name": "vow_", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "usr", + "type": "address" + } + ], + "name": "Deny", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "what", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "data", + "type": "uint256" + } + ], + "name": "File", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "FlashLoan", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "usr", + "type": "address" + } + ], + "name": "Rely", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "name": "VatDaiFlashLoan", + "type": "event" + }, + { + "inputs": [], + "name": "CALLBACK_SUCCESS", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CALLBACK_SUCCESS_VAT_DAI", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accrue", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "convert", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "dai", + "outputs": [ + { "internalType": "contract DaiLike", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "daiJoin", + "outputs": [ + { "internalType": "contract DaiJoinLike", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "usr", "type": "address" }], + "name": "deny", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "what", "type": "bytes32" }, + { "internalType": "uint256", "name": "data", "type": "uint256" } + ], + "name": "file", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "flashFee", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC3156FlashBorrower", + "name": "receiver", + "type": "address" + }, + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "flashLoan", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "max", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" } + ], + "name": "maxFlashLoan", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "usr", "type": "address" }], + "name": "rely", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "toll", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vat", + "outputs": [ + { "internalType": "contract VatLike_4", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVatDaiFlashBorrower", + "name": "receiver", + "type": "address" + }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "vatDaiFlashLoan", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vow", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "wards", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/src/fla.ts b/src/fla.ts index 6f168c6..993951e 100644 --- a/src/fla.ts +++ b/src/fla.ts @@ -1,102 +1,61 @@ -import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts"; +import { Address, BigInt, Bytes, ethereum } from "@graphprotocol/graph-ts"; import { ExecuteOperationCall, FLA, + LogFlashloan, OnFlashLoanCall, ReceiveFlashLoanCall, } from "../generated/FLA/FLA"; +import { FlashLoanFeePercentageChanged } from "../generated/Balancer/Balancer"; +import { File } from "../generated/Maker/Maker"; import { FeeData } from "../generated/schema"; // const DAI = new Address(0x6b175474e89094c44da98b954eedeac495271d0f); -export function handleExecuteOperation(call: ExecuteOperationCall): void { - // let assets = call.inputs._assets; - // let amounts = call.inputs._amounts; - // let user = call.inputs._initiator; - let fees = call.inputs._premiums; - let length = fees.length; - let data_ = call.inputs._data; +var balancerFee = BigInt.fromI32(0); +var makerBPS = BigInt.fromI32(0); +const e4 = BigInt.fromI32(10).pow(4); +const e14 = BigInt.fromI32(10).pow(14); +const e18 = BigInt.fromI32(10).pow(18); +export function handleFlashloan(event: LogFlashloan): void { + //balancer: result = product == 0 ? 0 : ((product - 1) / FixedPoint.ONE) + 1; + //maker: _mul(amount, toll) / WAD + let tokens = event.params.tokens; + let route = event.params.route.toI32(); + let amounts = event.params.amounts; + let user = event.params.account; - let decoded = ethereum.decode("(uint256,address[],uint256[],address,bytes)", data_)?.toTuple(); - if (decoded != undefined) { - let tokens = decoded[1].toArray(); - let amounts = decoded[2].toArray(); - let user = decoded[3].toAddress(); + for (let i = 0; i < tokens.length; i++) { + let id = user.toHexString() + "#" + tokens[i].toHexString(); + let data = createOrLoadFeeData(id); + data.user = user; + data.token = tokens[i]; - for (let i = 0; i < length; i++) { - let id = user.toHexString() + "#" + tokens[i].toAddress().toHexString(); - let data = createOrLoadFeeData(id); - data.user = user; - data.token = tokens[i].toAddress(); - - let instaAmt_ = amounts[i] - .toBigInt() - .times(BigInt.fromI32(5)) - .div(BigInt.fromI32(1e4)); - if (instaAmt_ > fees[i]) { - data.flaFee += instaAmt_.minus(fees[i]).toI32(); + let fees_ = BigInt.fromI32(0); + if (route == 1) { + fees_ = amounts[i].times(BigInt.fromI32(9)).div((e4)); + } else if (route == 2 || route == 3 || route == 4) { + fees_ = amounts[i].times(makerBPS).div((e4)); + } else if (route == 5 || route == 6 || route == 7) { + let pdt_ = amounts[i].times(balancerFee); + if (pdt_.toI32() == 0) { + fees_ = BigInt.fromI32(0); + } else { + fees_ = pdt_ + .minus(BigInt.fromI32(1)) + .div(e18) + .plus(BigInt.fromI32(1)); } - data.routeFee += fees[i].toI32(); - data.save(); } - } -} -export function handleOnFlashloan(call: OnFlashLoanCall): void { - // let amount = call.inputs._amount; - let fee = call.inputs._fee; - let data_ = call.inputs._data; - let decoded = ethereum.decode("(uint256,address[],uint256[],address,bytes)", data_)?.toTuple(); - if (decoded != undefined) { - let tokens = decoded[1].toArray(); - let amounts = decoded[2].toArray(); - let user = decoded[3].toAddress(); + let instaFees = amounts[i] + .times(BigInt.fromI32(5)) + .div(e4); - for (let i = 0; i < tokens.length; i++) { - let id = user.toHexString() + "#" + tokens[i].toAddress().toHexString(); - let data = createOrLoadFeeData(id); - data.user = user; - data.token = tokens[i].toAddress(); - - let instaAmt_ = amounts[i] - .toBigInt() - .times(BigInt.fromI32(5)) - .div(BigInt.fromI32(1e4)); - if (instaAmt_ > fee) { - data.flaFee += instaAmt_.minus(fee).toI32(); - } - data.routeFee += fee.toI32(); - data.save(); - } - } -} - -export function handleReceiveFlashloan(call: ReceiveFlashLoanCall): void { - let fees = call.inputs._fees; - let length = fees.length; - let data_ = call.inputs._data; - - let decoded = ethereum.decode("(uint256,address[],uint256[],address,bytes)", data_)?.toTuple(); - if (decoded != undefined) { - let tokens = decoded[1].toArray(); - let amounts = decoded[2].toArray(); - let user = decoded[3].toAddress(); - - for (let i = 0; i < length; i++) { - let id = user.toHexString() + "#" + tokens[i].toAddress().toHexString(); - let data = createOrLoadFeeData(id); - data.user = user; - data.token = tokens[i].toAddress(); - - let instaAmt_ = amounts[i] - .toBigInt() - .times(BigInt.fromI32(5)) - .div(BigInt.fromI32(1e4)); - if (instaAmt_ > fees[i]) { - data.flaFee += instaAmt_.minus(fees[i]).toI32(); - } - data.routeFee += fees[i].toI32(); - data.save(); + if (instaFees > fees_) { + data.flaFee = instaFees.minus(fees_).toI32(); } + data.routeFee = fees_.toI32(); + data.save(); } } @@ -111,3 +70,13 @@ export function createOrLoadFeeData(id: string): FeeData { } return data; } + +export function handleBalancerFeePercentChanged( + event: FlashLoanFeePercentageChanged +): void { + balancerFee = event.params.newFlashLoanFeePercentage; +} +export function handleMakerTollChanged(event: File): void { + if (event.params.what.toString() == "toll") + makerBPS = event.params.data.div(e14); +} diff --git a/subgraph.yaml b/subgraph.yaml index 46944ba..0912a44 100644 --- a/subgraph.yaml +++ b/subgraph.yaml @@ -17,11 +17,53 @@ dataSources: abis: - name: FLA file: ./abis/FLA.json - callHandlers: - - function: executeOperation(address[],uint256[],uint256[],address,bytes) - handler: handleExecuteOperation - - function: onFlashLoan(address,address,uint256,uint256,bytes) - handler: handleOnFlashloan - - function: receiveFlashLoan(address[],uint256[],uint256[],bytes) - handler: handleReceiveFlashloan + - name: Balancer + file: ./abis/Balancer.json + - name: Maker + file: ./abis/Maker.json + eventHandlers: + - event: LogFlashloan(indexed address,indexed uint256,address[],uint256[]) + handler: handleFlashloan + file: ./src/fla.ts + - kind: ethereum + name: Maker + network: mainnet + source: + address: "0x1EB4CF3A948E7D72A198fe073cCb8C7a948cD853" + abi: Maker + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - FeeData + abis: + - name: FLA + file: ./abis/FLA.json + - name: Maker + file: ./abis/Maker.json + eventHandlers: + - event: File(indexed bytes32,uint256) + handler: handleMakerTollChanged + file: ./src/fla.ts + - kind: ethereum + name: Balancer + network: mainnet + source: + address: "0xce88686553686DA562CE7Cea497CE749DA109f9F" + abi: Balancer + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - FeeData + abis: + - name: FLA + file: ./abis/FLA.json + - name: Balancer + file: ./abis/Balancer.json + eventHandlers: + - event: FlashLoanFeePercentageChanged(uint256) + handler: handleBalancerFeePercentChanged file: ./src/fla.ts