Skip to content

Commit

Permalink
Update the timestamp check function
Browse files Browse the repository at this point in the history
Due to Ubinetic stores timestamp with milliseconds format, we should add casting to standard-like timestamp object type.
Issue shown here: ecadlabs/taquito#3093
  • Loading branch information
LikoIlya committed Dec 6, 2024
1 parent d599ba4 commit 0c5c3ef
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 11 deletions.
56 changes: 54 additions & 2 deletions smart_contracts/oracle-on-demand.jsligo
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ namespace Utils {
// Utils
// -----
// #region
// Zero timestamp for casting
export const zeroTimestamp: timestamp = 0 as timestamp;
// Empty list of operations constant
export const no_operations: list<operation> = [];
// Disallows transfers of tez to the contract
Expand Down Expand Up @@ -118,6 +120,13 @@ namespace UbineticOracleUtils {
};
// #endregion
// -----------------------------------

@inline
function timestampFromMilliseconds(tsAsMilliseconds: timestamp): timestamp {
const tsAsIntWoMilliseconds: int = (tsAsMilliseconds - Utils.zeroTimestamp) / 1000;
const ts: timestamp = tsAsIntWoMilliseconds + Utils.zeroTimestamp;
return ts;
}

// Retrieve price from oracle
@inline
Expand All @@ -133,7 +142,7 @@ namespace UbineticOracleUtils {
);
// Assert data is recent. Checks if response timestamp is not older than delay in seconds.
Assert.Error.assert(
response.last_update_timestamp >= Tezos.get_now() - int(delay),
timestampFromMilliseconds(response.last_update_timestamp) >= Tezos.get_now() - int(delay),
ErrorCodes.stale_data
);
return response.price;
Expand Down Expand Up @@ -251,10 +260,22 @@ export namespace KolibriOracleAdapter {
// ---------------
// #region
const xtzValue = 2310000n;
const twoDays = 86_400 * 2
// NOTE: the Ubinetic oracle store the timestamps in non-standard way, with milliseconds.
// Highlighted here: https://discord.com/channels/790468417844412456/790469864934211604/1314628665669058630
// Issue opened here: https://github.com/ecadlabs/taquito/issues/3093
const nowInMilliseconds = ((Tezos.get_now() - Utils.zeroTimestamp) * 1000) + Utils.zeroTimestamp;
const twoDaysEarlierInMilliseconds = ((Tezos.get_now() - twoDays) - Utils.zeroTimestamp) * 1000 + Utils.zeroTimestamp;
const mockedOracle = contract_of(Mocks.FakeOnDemandOracle);
const oracleStorage: Mocks.FakeOnDemandOracle.storage = {
prices: Big_map.literal([
["XTZUSDT", {price: xtzValue, last_update_timestamp: Tezos.get_now()}],
["XTZUSDT", {price: xtzValue, last_update_timestamp: nowInMilliseconds}],
])
};

const oracleStorageOutdated: Mocks.FakeOnDemandOracle.storage = {
prices: Big_map.literal([
["XTZUSDT", {price: xtzValue, last_update_timestamp: twoDaysEarlierInMilliseconds}],
])
};
const mockedCallbackReceiver = contract_of(Mocks.FakeCallbackReceiver);
Expand Down Expand Up @@ -339,6 +360,36 @@ function test_retrieve(): unit {
return Assert.assert(Test.Next.Typed_address.get_storage(callbackContract.taddr) == expectedValue);
}

function test_outdated_retrieve(): unit {
Test.Next.IO.log("getXtzUsdRate - failed to retrieve outdated value");
const fakeOracle = Test.Next.Originate.contract(
mockedOracle,
oracleStorageOutdated,
0mutez
);
const adapterStorage: KolibriOracleAdapter.storage = {
oracleProxyContractAddress: Test.Next.Typed_address.to_address(fakeOracle.taddr),
maxDataDelaySec: 60n * 30n,
governorContractAddress: admin_account,
};
const adapterContract = Test.Next.Originate.contract(
adapter,
adapterStorage,
0mutez
);
const callbackContract = Test.Next.Originate.contract(
mockedCallbackReceiver,
callbackStorage,
0mutez
);

const callback: contract<nat> = Test.Next.Typed_address.get_entrypoint("receivePriceCallback", callbackContract.taddr);
const result = Test.Next.Contract.transfer(Test.Next.Typed_address.get_entrypoint("getXtzUsdRate", adapterContract.taddr), callback, 0mutez);
match(result) {
when(Fail(_x)): Test.Next.IO.log("[Success] Failed as expected");
when(Success(_s)): failwith("[Fail] This should not succeed")
};
}
// -------
// default
// -------
Expand Down Expand Up @@ -460,4 +511,5 @@ const test4 = test_governor_set_governor();
const test5 = test_with_amount();
const test6 = test_not_governor_set_delay();
const test7 = test_not_governor_set_governor();
const test8 = test_outdated_retrieve();
// #endregion
27 changes: 18 additions & 9 deletions smart_contracts/oracle-on-demand.tz
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
(nat %maxDataDelaySec)
(address %governorContractAddress)) ;
code { PUSH string "15" ;
PUSH string "4" ;
PUSH timestamp 0 ;
NIL operation ;
DIG 3 ;
UNPAIR ;
Expand All @@ -23,9 +23,8 @@
SWAP }
{ IF_LEFT
{ DIG 2 ;
DROP ;
DIG 3 ;
DROP 2 ;
DIG 2 ;
PUSH mutez 0 ;
AMOUNT ;
COMPARE ;
Expand All @@ -45,8 +44,16 @@
INT ;
NOW ;
SUB ;
DUP 3 ;
PUSH int 1000 ;
DUP 7 ;
DUP 5 ;
CDR ;
SUB ;
EDIV ;
IF_NONE { PUSH string "DIV by 0" ; FAILWITH } {} ;
CAR ;
DIG 6 ;
ADD ;
COMPARE ;
GE ;
IF { DROP } { FAILWITH } ;
Expand All @@ -61,28 +68,30 @@
DIG 4 ;
TRANSFER_TOKENS ;
CONS }
{ IF_LEFT
{ DIG 4 ;
{ DIG 3 ;
DROP ;
IF_LEFT
{ DIG 3 ;
PUSH mutez 0 ;
AMOUNT ;
COMPARE ;
EQ ;
IF { DROP } { FAILWITH } ;
DIG 3 ;
PUSH string "4" ;
DUP 3 ;
GET 4 ;
SENDER ;
COMPARE ;
EQ ;
IF { DROP } { FAILWITH } ;
UPDATE 4 }
{ DIG 4 ;
{ DIG 3 ;
PUSH mutez 0 ;
AMOUNT ;
COMPARE ;
EQ ;
IF { DROP } { FAILWITH } ;
DIG 3 ;
PUSH string "4" ;
DUP 3 ;
GET 4 ;
SENDER ;
Expand Down

0 comments on commit 0c5c3ef

Please sign in to comment.