The Uniswap contract, and mechanism behind the contract, is an interesting contract to study. We won't go through all Uniswap contracts, but just how a transaction works and visualizing the various coins that were exchanged to complete the transaction.
We'll start with the contract address we're interested in: 0x7a250d5630b4cf539739df2c5dacb4c659f2488d
Let's grab a few sample Uniswap transactions using the Sort API to see what we can learn:
POST https://api.sort.xyz/v0/transaction/
Body:
{
"contract_address" : "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"limit": 5
}
The API call above will return the latest 5 Uniswap transactions, sorted by date descending. You may notice there are 5 primary Uniswap trading functions in the transactions:
- swapExactTokensForTokens
- swapExactETHForTokens
- swapExactTokensForETH
- swapTokensForExactTokens
- swapETHForExactTokens
Let's focus on 'swapExactTokensForTokens' and refine our API call:
POST https://api.sort.xyz/v0/transaction/
Body:
{
"contract_address" : "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"contract_function" : "swapExactTokensForTokens",
"limit": 10
}
Let's look at this transaction (you can follow along in your web browser by accessing this link for the transaction hash):
0xb5f32cd7524fc4f33fd656625bb98dfed5d1396f9c6580b82a9501a89c5569f5
GET https://api.sort.xyz/v0/transaction/0xb5f32cd7524fc4f33fd656625bb98dfed5d1396f9c6580b82a9501a89c5569f5
The first thing we'll want to look at is the function name and parameters passed into it, this is located in the top level "function" field:
"function": {
"name": "swapExactTokensForTokens",
"params": [
{
"name": "amountIn",
"value": "100000000000000000000",
"type": "uint256"
},
{
"name": "amountOutMin",
"value": "37541924376765909332716544",
"type": "uint256"
},
{
"name": "path",
"value": [
{
"raw": "0xb1191f691a355b43542bea9b8847bc73e7abb137",
"name": "Kirobo",
"symbol": "KIRO"
},
{
"raw": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"name": "ETH",
"symbol": "ETH"
},
{
"raw": "0x1c7e83f8c581a967940dbfa7984744646ae46b29",
"name": "random",
"symbol": "RND"
}
],
"type": "address[]"
},
{
"name": "to",
"value": "0xeb9fbacfac3dceded5dc45daa3b319a9a1593dc7",
"type": "address"
},
{
"name": "deadline",
"value": "1647875834",
"type": "uint256"
}
]
}
By looking at the function call, you can get an idea of the transaction that is being requested:
- Trade "100000000000000000000" KIRO tokens for "37541924376765909332716544" RND tokens (you'll notice the numbers seem very large, this is because they have not been shifted X decimals places based on the contract value)
Now, let's look at the logs to see what actually happened. The logs can be found in the top level "logs" field:
"logs": {
"functions": [
{
"name": "Transfer",
"type": "event",
"params": [
{
"value": "0xeb9fbacfac3dceded5dc45daa3b319a9a1593dc7",
"name": "from",
"symbol": null,
"type": "address"
},
{
"value": "0x5cd136e8197be513b06d39730dc674b1e0f6b7da",
"name": "to",
"symbol": "UNI-V2",
"type": "address"
},
{
"value": "100000000000000000000",
"type": "uint256",
"name": "value"
}
],
"function_address": {
"value": "0xb1191f691a355b43542bea9b8847bc73e7abb137",
"name": "Kirobo",
"symbol": "KIRO"
}
},
{
"name": "Approval",
"type": "event",
"params": [
{
"value": "0xeb9fbacfac3dceded5dc45daa3b319a9a1593dc7",
"name": "owner",
"symbol": null,
"type": "address"
},
{
"value": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"name": "spender",
"symbol": null,
"type": "address"
},
{
"value": "115792089237316195423570985008687907853269984665640564039357584007913129639935",
"type": "uint256",
"name": "value"
}
],
"function_address": {
"value": "0xb1191f691a355b43542bea9b8847bc73e7abb137",
"name": "Kirobo",
"symbol": "KIRO"
}
},
{
"name": "Transfer",
"type": "event",
"params": [
{
"value": "0x5cd136e8197be513b06d39730dc674b1e0f6b7da",
"name": "src",
"symbol": "UNI-V2",
"type": "address"
},
{
"value": "0x5449bd1a97296125252db2d9cf23d5d6e30ca3c1",
"name": "dst",
"symbol": "UNI-V2",
"type": "address"
},
{
"value": "4305548873194210",
"type": "uint256",
"name": "wad"
}
],
"function_address": {
"value": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
"name": "ETH",
"symbol": "ETH"
}
},
{
"name": "Sync",
"type": "event",
"params": [
{
"value": "5340477822266522423654997",
"type": "uint112",
"name": "reserve0"
},
{
"value": "230624450502417018204",
"type": "uint112",
"name": "reserve1"
}
],
"function_address": {
"value": "0x5cd136e8197be513b06d39730dc674b1e0f6b7da",
"name": "Uniswap V2",
"symbol": "UNI-V2"
}
},
{
"name": "Swap",
"type": "event",
"params": [
{
"value": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"name": "sender",
"symbol": null,
"type": "address"
},
{
"value": "100000000000000000000",
"type": "uint256",
"name": "amount0In"
},
{
"value": "0",
"type": "uint256",
"name": "amount1In"
},
{
"value": "0",
"type": "uint256",
"name": "amount0Out"
},
{
"value": "4305548873194210",
"type": "uint256",
"name": "amount1Out"
},
{
"value": "0x5449bd1a97296125252db2d9cf23d5d6e30ca3c1",
"name": "to",
"symbol": "UNI-V2",
"type": "address"
}
],
"function_address": {
"value": "0x5cd136e8197be513b06d39730dc674b1e0f6b7da",
"name": "Uniswap V2",
"symbol": "UNI-V2"
}
},
{
"name": "Transfer",
"type": "event",
"params": [
{
"value": "0x5449bd1a97296125252db2d9cf23d5d6e30ca3c1",
"name": "from",
"symbol": "UNI-V2",
"type": "address"
},
{
"value": "0xeb9fbacfac3dceded5dc45daa3b319a9a1593dc7",
"name": "to",
"symbol": null,
"type": "address"
},
{
"value": "37579466301142675242049261",
"type": "uint256",
"name": "value"
}
],
"function_address": {
"value": "0x1c7e83f8c581a967940dbfa7984744646ae46b29",
"name": "random",
"symbol": "RND"
}
},
{
"name": "Sync",
"type": "event",
"params": [
{
"value": "18139246877011718508631881984",
"type": "uint112",
"name": "reserve0"
},
{
"value": "2076317830422973219",
"type": "uint112",
"name": "reserve1"
}
],
"function_address": {
"value": "0x5449bd1a97296125252db2d9cf23d5d6e30ca3c1",
"name": "Uniswap V2",
"symbol": "UNI-V2"
}
},
{
"name": "Swap",
"type": "event",
"params": [
{
"value": "0x7a250d5630b4cf539739df2c5dacb4c659f2488d",
"name": "sender",
"symbol": null,
"type": "address"
},
{
"value": "0",
"type": "uint256",
"name": "amount0In"
},
{
"value": "4305548873194210",
"type": "uint256",
"name": "amount1In"
},
{
"value": "37579466301142675242049261",
"type": "uint256",
"name": "amount0Out"
},
{
"value": "0",
"type": "uint256",
"name": "amount1Out"
},
{
"value": "0xeb9fbacfac3dceded5dc45daa3b319a9a1593dc7",
"name": "to",
"symbol": null,
"type": "address"
}
],
"function_address": {
"value": "0x5449bd1a97296125252db2d9cf23d5d6e30ca3c1",
"name": "Uniswap V2",
"symbol": "UNI-V2"
}
}
],
"num_logs": 8,
"status": 1
}
A few notes:
- The "status" field is 1 or 0, and tells us whether the transaction was successful.
- The "function_address" field tells us on which contract the function was executed.
We can see 8 function calls. There is a transfer of "KIRO" to the contract from the initiator (Transfer/Approval), then swap from "KIRO" to "ETH", then the final swap from "ETH" to "RND". The "RND" is then sent back to the initiator of the request.
We can spend a lot more time going through each function in-depth, this tutorial was meant to be a primer to get you started walking through transactions and using the Sort API.
Feel free to ask more questions on our Discord, or continue on to the Sort API documentation.
Top comments (0)