@@ -5,21 +5,17 @@ use graph::components::metrics::subgraph::SubgraphInstanceMetrics;
55use graph:: components:: store:: { EthereumCallCache , StoredDynamicDataSource } ;
66use graph:: components:: subgraph:: { HostMetrics , InstanceDSTemplateInfo , MappingError } ;
77use graph:: components:: trigger_processor:: RunnableTriggers ;
8- use graph:: data:: value:: Word ;
9- use graph:: data_source:: common:: { MappingABI , UnresolvedMappingABI } ;
8+ use graph:: data_source:: common:: { CallDecls , MappingABI , UnresolvedMappingABI } ;
109use graph:: data_source:: CausalityRegion ;
1110use graph:: env:: ENV_VARS ;
1211use graph:: futures03:: future:: try_join;
1312use graph:: futures03:: stream:: FuturesOrdered ;
1413use graph:: futures03:: TryStreamExt ;
1514use graph:: prelude:: ethabi:: ethereum_types:: H160 ;
1615use graph:: prelude:: ethabi:: { StateMutability , Token } ;
17- use graph:: prelude:: lazy_static;
18- use graph:: prelude:: regex:: Regex ;
1916use graph:: prelude:: { Link , SubgraphManifestValidationError } ;
2017use graph:: slog:: { debug, error, o, trace} ;
2118use itertools:: Itertools ;
22- use serde:: de;
2319use serde:: de:: Error as ErrorD ;
2420use serde:: { Deserialize , Deserializer } ;
2521use std:: collections:: HashSet ;
@@ -31,7 +27,6 @@ use tiny_keccak::{keccak256, Keccak};
3127
3228use graph:: {
3329 blockchain:: { self , Blockchain } ,
34- derive:: CheapClone ,
3530 prelude:: {
3631 async_trait,
3732 ethabi:: { Address , Event , Function , LogParam , ParamType , RawLog } ,
@@ -1569,225 +1564,3 @@ fn string_to_h256(s: &str) -> H256 {
15691564pub struct TemplateSource {
15701565 pub abi : String ,
15711566}
1572-
1573- /// Internal representation of declared calls. In the manifest that's
1574- /// written as part of an event handler as
1575- /// ```yaml
1576- /// calls:
1577- /// - myCall1: Contract[address].function(arg1, arg2, ...)
1578- /// - ..
1579- /// ```
1580- ///
1581- /// The `address` and `arg` fields can be either `event.address` or
1582- /// `event.params.<name>`. Each entry under `calls` gets turned into a
1583- /// `CallDcl`
1584- #[ derive( Clone , CheapClone , Debug , Default , Hash , Eq , PartialEq ) ]
1585- pub struct CallDecls {
1586- pub decls : Arc < Vec < CallDecl > > ,
1587- readonly : ( ) ,
1588- }
1589-
1590- /// A single call declaration, like `myCall1:
1591- /// Contract[address].function(arg1, arg2, ...)`
1592- #[ derive( Clone , Debug , Hash , Eq , PartialEq ) ]
1593- pub struct CallDecl {
1594- /// A user-defined label
1595- pub label : String ,
1596- /// The call expression
1597- pub expr : CallExpr ,
1598- readonly : ( ) ,
1599- }
1600- impl CallDecl {
1601- fn address ( & self , log : & Log , params : & [ LogParam ] ) -> Result < H160 , Error > {
1602- let address = match & self . expr . address {
1603- CallArg :: Address => log. address ,
1604- CallArg :: HexAddress ( address) => * address,
1605- CallArg :: Param ( name) => {
1606- let value = params
1607- . iter ( )
1608- . find ( |param| & param. name == name. as_str ( ) )
1609- . ok_or_else ( || anyhow ! ( "unknown param {name}" ) ) ?
1610- . value
1611- . clone ( ) ;
1612- value
1613- . into_address ( )
1614- . ok_or_else ( || anyhow ! ( "param {name} is not an address" ) ) ?
1615- }
1616- } ;
1617- Ok ( address)
1618- }
1619-
1620- fn args ( & self , log : & Log , params : & [ LogParam ] ) -> Result < Vec < Token > , Error > {
1621- self . expr
1622- . args
1623- . iter ( )
1624- . map ( |arg| match arg {
1625- CallArg :: Address => Ok ( Token :: Address ( log. address ) ) ,
1626- CallArg :: HexAddress ( address) => Ok ( Token :: Address ( * address) ) ,
1627- CallArg :: Param ( name) => {
1628- let value = params
1629- . iter ( )
1630- . find ( |param| & param. name == name. as_str ( ) )
1631- . ok_or_else ( || anyhow ! ( "unknown param {name}" ) ) ?
1632- . value
1633- . clone ( ) ;
1634- Ok ( value)
1635- }
1636- } )
1637- . collect ( )
1638- }
1639- }
1640-
1641- impl < ' de > de:: Deserialize < ' de > for CallDecls {
1642- fn deserialize < D > ( deserializer : D ) -> Result < CallDecls , D :: Error >
1643- where
1644- D : de:: Deserializer < ' de > ,
1645- {
1646- let decls: std:: collections:: HashMap < String , String > =
1647- de:: Deserialize :: deserialize ( deserializer) ?;
1648- let decls = decls
1649- . into_iter ( )
1650- . map ( |( name, expr) | {
1651- expr. parse :: < CallExpr > ( ) . map ( |expr| CallDecl {
1652- label : name,
1653- expr,
1654- readonly : ( ) ,
1655- } )
1656- } )
1657- . collect :: < Result < _ , _ > > ( )
1658- . map ( |decls| Arc :: new ( decls) )
1659- . map_err ( de:: Error :: custom) ?;
1660- Ok ( CallDecls {
1661- decls,
1662- readonly : ( ) ,
1663- } )
1664- }
1665- }
1666-
1667- #[ derive( Clone , Debug , Hash , Eq , PartialEq ) ]
1668- pub struct CallExpr {
1669- pub abi : Word ,
1670- pub address : CallArg ,
1671- pub func : Word ,
1672- pub args : Vec < CallArg > ,
1673- readonly : ( ) ,
1674- }
1675-
1676- /// Parse expressions of the form `Contract[address].function(arg1, arg2,
1677- /// ...)` where the `address` and the args are either `event.address` or
1678- /// `event.params.<name>`.
1679- ///
1680- /// The parser is pretty awful as it generates error messages that aren't
1681- /// very helpful. We should replace all this with a real parser, most likely
1682- /// `combine` which is what `graphql_parser` uses
1683- impl FromStr for CallExpr {
1684- type Err = anyhow:: Error ;
1685-
1686- fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
1687- lazy_static ! {
1688- static ref RE : Regex = Regex :: new(
1689- r"(?x)
1690- (?P<abi>[a-zA-Z0-9_]+)\[
1691- (?P<address>[^]]+)\]
1692- \.
1693- (?P<func>[a-zA-Z0-9_]+)\(
1694- (?P<args>[^)]*)
1695- \)"
1696- )
1697- . unwrap( ) ;
1698- }
1699- let x = RE
1700- . captures ( s)
1701- . ok_or_else ( || anyhow ! ( "invalid call expression `{s}`" ) ) ?;
1702- let abi = Word :: from ( x. name ( "abi" ) . unwrap ( ) . as_str ( ) ) ;
1703- let address = x. name ( "address" ) . unwrap ( ) . as_str ( ) . parse ( ) ?;
1704- let func = Word :: from ( x. name ( "func" ) . unwrap ( ) . as_str ( ) ) ;
1705- let args: Vec < CallArg > = x
1706- . name ( "args" )
1707- . unwrap ( )
1708- . as_str ( )
1709- . split ( ',' )
1710- . filter ( |s| !s. is_empty ( ) )
1711- . map ( |s| s. trim ( ) . parse :: < CallArg > ( ) )
1712- . collect :: < Result < _ , _ > > ( ) ?;
1713- Ok ( CallExpr {
1714- abi,
1715- address,
1716- func,
1717- args,
1718- readonly : ( ) ,
1719- } )
1720- }
1721- }
1722-
1723- #[ derive( Clone , Debug , Hash , Eq , PartialEq ) ]
1724- pub enum CallArg {
1725- HexAddress ( Address ) ,
1726- Address ,
1727- Param ( Word ) ,
1728- }
1729-
1730- lazy_static ! {
1731- // Matches a 40-character hexadecimal string prefixed with '0x', typical for Ethereum addresses
1732- static ref ADDR_RE : Regex = Regex :: new( r"^0x[0-9a-fA-F]{40}$" ) . unwrap( ) ;
1733- }
1734-
1735- impl FromStr for CallArg {
1736- type Err = anyhow:: Error ;
1737-
1738- fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
1739- if ADDR_RE . is_match ( s) {
1740- if let Ok ( parsed_address) = Address :: from_str ( s) {
1741- return Ok ( CallArg :: HexAddress ( parsed_address) ) ;
1742- }
1743- }
1744-
1745- let mut parts = s. split ( '.' ) ;
1746- match ( parts. next ( ) , parts. next ( ) , parts. next ( ) ) {
1747- ( Some ( "event" ) , Some ( "address" ) , None ) => Ok ( CallArg :: Address ) ,
1748- ( Some ( "event" ) , Some ( "params" ) , Some ( param) ) => Ok ( CallArg :: Param ( Word :: from ( param) ) ) ,
1749- _ => Err ( anyhow ! ( "invalid call argument `{}`" , s) ) ,
1750- }
1751- }
1752- }
1753-
1754- #[ test]
1755- fn test_call_expr ( ) {
1756- let expr: CallExpr = "ERC20[event.address].balanceOf(event.params.token)"
1757- . parse ( )
1758- . unwrap ( ) ;
1759- assert_eq ! ( expr. abi, "ERC20" ) ;
1760- assert_eq ! ( expr. address, CallArg :: Address ) ;
1761- assert_eq ! ( expr. func, "balanceOf" ) ;
1762- assert_eq ! ( expr. args, vec![ CallArg :: Param ( "token" . into( ) ) ] ) ;
1763-
1764- let expr: CallExpr = "Pool[event.params.pool].fees(event.params.token0, event.params.token1)"
1765- . parse ( )
1766- . unwrap ( ) ;
1767- assert_eq ! ( expr. abi, "Pool" ) ;
1768- assert_eq ! ( expr. address, CallArg :: Param ( "pool" . into( ) ) ) ;
1769- assert_eq ! ( expr. func, "fees" ) ;
1770- assert_eq ! (
1771- expr. args,
1772- vec![
1773- CallArg :: Param ( "token0" . into( ) ) ,
1774- CallArg :: Param ( "token1" . into( ) )
1775- ]
1776- ) ;
1777-
1778- let expr: CallExpr = "Pool[event.address].growth()" . parse ( ) . unwrap ( ) ;
1779- assert_eq ! ( expr. abi, "Pool" ) ;
1780- assert_eq ! ( expr. address, CallArg :: Address ) ;
1781- assert_eq ! ( expr. func, "growth" ) ;
1782- assert_eq ! ( expr. args, vec![ ] ) ;
1783-
1784- let expr: CallExpr = "Pool[0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF].growth(0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF)"
1785- . parse ( )
1786- . unwrap ( ) ;
1787- let call_arg =
1788- CallArg :: HexAddress ( H160 :: from_str ( "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF" ) . unwrap ( ) ) ;
1789- assert_eq ! ( expr. abi, "Pool" ) ;
1790- assert_eq ! ( expr. address, call_arg) ;
1791- assert_eq ! ( expr. func, "growth" ) ;
1792- assert_eq ! ( expr. args, vec![ call_arg] ) ;
1793- }
0 commit comments