@@ -1904,4 +1904,173 @@ public async Task ExtendSeedExpirationTime_Test(string symbol, long expirationTi
19041904
19051905 await TokenContractStub . ExtendSeedExpirationTime . CallAsync ( input ) ;
19061906 }
1907+
1908+ [ Fact ]
1909+ public async Task MultiTokenContract_Transfer_BlackList_Test ( )
1910+ {
1911+ await MultiTokenContract_Approve_Test ( ) ;
1912+
1913+ var trafficToken = "TRAFFIC" ;
1914+ await CreateAndIssueCustomizeTokenAsync ( DefaultAddress , trafficToken , 10000 , 10000 ) ;
1915+
1916+ // 1. Non-owner cannot add to blacklist
1917+ var addBlackListResult = await TokenContractStubUser . AddToTransferBlackList . SendWithExceptionAsync ( DefaultAddress ) ;
1918+ addBlackListResult . TransactionResult . Status . ShouldBe ( TransactionResultStatus . Failed ) ;
1919+ addBlackListResult . TransactionResult . Error . ShouldContain ( "Unauthorized behavior" ) ;
1920+ var isInTransferBlackList = await TokenContractStubUser . IsInTransferBlackList . CallAsync ( DefaultAddress ) ;
1921+ isInTransferBlackList . Value . ShouldBe ( false ) ;
1922+
1923+ // 2. Owner adds DefaultAddress to blacklist via parliament proposal
1924+ var defaultParliament = await ParliamentContractStub . GetDefaultOrganizationAddress . CallAsync ( new Empty ( ) ) ;
1925+ var proposalId = await CreateProposalAsync ( TokenContractAddress , defaultParliament , nameof ( TokenContractStub . AddToTransferBlackList ) , DefaultAddress ) ;
1926+ await ApproveWithMinersAsync ( proposalId ) ;
1927+ await ParliamentContractStub . Release . SendAsync ( proposalId ) ;
1928+ isInTransferBlackList = await TokenContractStubUser . IsInTransferBlackList . CallAsync ( DefaultAddress ) ;
1929+ isInTransferBlackList . Value . ShouldBe ( true ) ;
1930+
1931+ // 3. Transfer should fail when sender is in blacklist
1932+ var transferResult = ( await TokenContractStub . Transfer . SendWithExceptionAsync ( new TransferInput
1933+ {
1934+ Amount = Amount ,
1935+ Memo = "blacklist test" ,
1936+ Symbol = AliceCoinTokenInfo . Symbol ,
1937+ To = User1Address
1938+ } ) ) . TransactionResult ;
1939+ transferResult . Status . ShouldBe ( TransactionResultStatus . Failed ) ;
1940+ transferResult . Error . ShouldContain ( "From address is in transfer blacklist" ) ;
1941+
1942+ // 4. TransferFrom should fail when from address is in blacklist
1943+ var user1Stub = GetTester < TokenContractImplContainer . TokenContractImplStub > ( TokenContractAddress , User1KeyPair ) ;
1944+ var transferFromResult = ( await user1Stub . TransferFrom . SendWithExceptionAsync ( new TransferFromInput
1945+ {
1946+ Amount = Amount ,
1947+ From = DefaultAddress ,
1948+ Memo = "blacklist test" ,
1949+ Symbol = AliceCoinTokenInfo . Symbol ,
1950+ To = User1Address
1951+ } ) ) . TransactionResult ;
1952+ transferFromResult . Status . ShouldBe ( TransactionResultStatus . Failed ) ;
1953+ transferFromResult . Error . ShouldContain ( "From address is in transfer blacklist" ) ;
1954+
1955+ // 5. CrossChainTransfer should fail when sender is in blacklist
1956+ var crossChainTransferResult = ( await TokenContractStub . CrossChainTransfer . SendWithExceptionAsync ( new CrossChainTransferInput
1957+ {
1958+ Symbol = AliceCoinTokenInfo . Symbol ,
1959+ Amount = Amount ,
1960+ To = User1Address ,
1961+ IssueChainId = 9992731 ,
1962+ Memo = "blacklist test" ,
1963+ ToChainId = 9992732
1964+ } ) ) . TransactionResult ;
1965+ crossChainTransferResult . Status . ShouldBe ( TransactionResultStatus . Failed ) ;
1966+ crossChainTransferResult . Error . ShouldContain ( "Sender is in transfer blacklist" ) ;
1967+
1968+ // 6. Lock should fail when sender is in blacklist
1969+ var lockId = HashHelper . ComputeFrom ( "lockId" ) ;
1970+ var lockTokenResult = ( await BasicFunctionContractStub . LockToken . SendWithExceptionAsync ( new LockTokenInput
1971+ {
1972+ Address = DefaultAddress ,
1973+ Amount = Amount ,
1974+ Symbol = AliceCoinTokenInfo . Symbol ,
1975+ LockId = lockId ,
1976+ Usage = "Testing."
1977+ } ) ) . TransactionResult ;
1978+ lockTokenResult . Status . ShouldBe ( TransactionResultStatus . Failed ) ;
1979+ lockTokenResult . Error . ShouldContain ( "From address is in transfer blacklist" ) ;
1980+
1981+ // 7. Transfer to contract should fail when sender is in blacklist
1982+ var transferToContractResult = ( await BasicFunctionContractStub . TransferTokenToContract . SendWithExceptionAsync (
1983+ new TransferTokenToContractInput
1984+ {
1985+ Amount = Amount ,
1986+ Symbol = AliceCoinTokenInfo . Symbol
1987+ } ) ) . TransactionResult ;
1988+ transferToContractResult . Status . ShouldBe ( TransactionResultStatus . Failed ) ;
1989+ transferToContractResult . Error . ShouldContain ( "From address is in transfer blacklist" ) ;
1990+
1991+ // 8. AdvanceResourceToken should fail when sender is in blacklist
1992+ var advanceRet = await TokenContractStub . AdvanceResourceToken . SendWithExceptionAsync (
1993+ new AdvanceResourceTokenInput
1994+ {
1995+ ContractAddress = BasicFunctionContractAddress ,
1996+ Amount = Amount ,
1997+ ResourceTokenSymbol = trafficToken
1998+ } ) ;
1999+ advanceRet . TransactionResult . Status . ShouldBe ( TransactionResultStatus . Failed ) ;
2000+ advanceRet . TransactionResult . Error . ShouldContain ( "From address is in transfer blacklist" ) ;
2001+
2002+ // 9. Non-owner cannot remove from blacklist
2003+ var removeBlackListResult = await TokenContractStubUser . RemoveFromTransferBlackList . SendWithExceptionAsync ( DefaultAddress ) ;
2004+ removeBlackListResult . TransactionResult . Status . ShouldBe ( TransactionResultStatus . Failed ) ;
2005+ removeBlackListResult . TransactionResult . Error . ShouldContain ( "Unauthorized behavior" ) ;
2006+
2007+ // 10. Owner removes DefaultAddress from blacklist via parliament proposal
2008+ var removeProposalId = await CreateProposalAsync ( TokenContractAddress , defaultParliament , nameof ( TokenContractStub . RemoveFromTransferBlackList ) , DefaultAddress ) ;
2009+ await ApproveWithMinersAsync ( removeProposalId ) ;
2010+ await ParliamentContractStub . Release . SendAsync ( removeProposalId ) ;
2011+ isInTransferBlackList = await TokenContractStubUser . IsInTransferBlackList . CallAsync ( DefaultAddress ) ;
2012+ isInTransferBlackList . Value . ShouldBe ( false ) ;
2013+
2014+ // 11. Transfer should succeed after removing from blacklist
2015+ var transferResult2 = await TokenContractStub . Transfer . SendAsync ( new TransferInput
2016+ {
2017+ Amount = Amount ,
2018+ Memo = "blacklist test" ,
2019+ Symbol = AliceCoinTokenInfo . Symbol ,
2020+ To = User1Address
2021+ } ) ;
2022+ transferResult2 . TransactionResult . Status . ShouldBe ( TransactionResultStatus . Mined ) ;
2023+
2024+ // 12. TransferFrom should succeed after removing from blacklist
2025+ transferFromResult = ( await user1Stub . TransferFrom . SendAsync ( new TransferFromInput
2026+ {
2027+ Amount = Amount ,
2028+ From = DefaultAddress ,
2029+ Memo = "blacklist test" ,
2030+ Symbol = AliceCoinTokenInfo . Symbol ,
2031+ To = User1Address
2032+ } ) ) . TransactionResult ;
2033+ transferFromResult . Status . ShouldBe ( TransactionResultStatus . Mined ) ;
2034+
2035+ // 13. CrossChainTransfer should succeed after removing from blacklist
2036+ crossChainTransferResult = ( await TokenContractStub . CrossChainTransfer . SendAsync ( new CrossChainTransferInput
2037+ {
2038+ Symbol = AliceCoinTokenInfo . Symbol ,
2039+ Amount = Amount ,
2040+ To = User1Address ,
2041+ IssueChainId = 9992731 ,
2042+ Memo = "blacklist test" ,
2043+ ToChainId = 9992732
2044+ } ) ) . TransactionResult ;
2045+ crossChainTransferResult . Status . ShouldBe ( TransactionResultStatus . Mined ) ;
2046+
2047+ // 14. Lock should succeed after removing from blacklist
2048+ lockTokenResult = ( await BasicFunctionContractStub . LockToken . SendAsync ( new LockTokenInput
2049+ {
2050+ Address = DefaultAddress ,
2051+ Amount = Amount ,
2052+ Symbol = AliceCoinTokenInfo . Symbol ,
2053+ LockId = lockId ,
2054+ Usage = "Testing."
2055+ } ) ) . TransactionResult ;
2056+ lockTokenResult . Status . ShouldBe ( TransactionResultStatus . Mined ) ;
2057+
2058+ // 15. Transfer to contract should succeed after removing from blacklist
2059+ transferToContractResult = ( await BasicFunctionContractStub . TransferTokenToContract . SendAsync ( new TransferTokenToContractInput
2060+ {
2061+ Amount = Amount ,
2062+ Symbol = AliceCoinTokenInfo . Symbol
2063+ } ) ) . TransactionResult ;
2064+ transferToContractResult . Status . ShouldBe ( TransactionResultStatus . Mined ) ;
2065+
2066+ // 16. AdvanceResourceToken should succeed after removing from blacklist
2067+ advanceRet = await TokenContractStub . AdvanceResourceToken . SendAsync (
2068+ new AdvanceResourceTokenInput
2069+ {
2070+ ContractAddress = BasicFunctionContractAddress ,
2071+ Amount = Amount ,
2072+ ResourceTokenSymbol = trafficToken
2073+ } ) ;
2074+ advanceRet . TransactionResult . Status . ShouldBe ( TransactionResultStatus . Mined ) ;
2075+ }
19072076}
0 commit comments